How to stop the Parallel for loop process outside the loop? - c#

I start the parallel for loop process from button click(Start Button). The parallel process going well but at the time I moved another page then I return to current parallel process page,process going well.
I try to stop the Parallel process from another button click(button stop). Is it possible?
protected void btnstart_Click(object sender, EventArgs e)
{
try
{
Parallel.For(0, dtrecord.Rows.Count, pOptions1, (j, pls) =>
{
if (Session["Stop"] != null)
{
pls.Stop();
Session.Remove("Stop2");
Session["ParallelStopped"] = 1;
}
else
{
Checkrecords(dtrecord, ImportFileID, j);
}
});
}
catch (Exception ex)
{
Log.Trace("Error occured in btnstop_Click");
Log.Error(ex.Message);
}
}
protected void btnstop_Click(object sender, EventArgs e)
{
try
{
Session["Stop"] = 1;
Session.Remove("start");
Session["start"] = null;
BindImportfileDetails();
BindImportrecordsdetails(hidimid.Value);
bindimportrecords();
Getrecordstatuscount();
Log.Trace("User has been stopping the import process");
}
catch (Exception ex)
{
Log.Trace("Error occured in btnstop_Click");
Log.Error(ex.Message);
}
}

Related

Waiting for javascript-rendered page loading in CefSharp

I started to learn CefSharp. It is a convinient tool for web scraping. But I have a problem.
I want to wait for a page to be loaded. But the page loading is completed by ajax. And I'm waiting for some html tags.
I wrote like this.
public ChromiumWebBrowser brser;
Thread main_thread;
public Form1()
{
brser = new ChromiumWebBrowser("some_url_here");
panelBrowser.Controls.Add(brser);
brser.Dock = DockStyle.Fill;
main_thread = new Thread(mainStart);
main_thread.Start();
}
private void mainStart()
{
brser.LoadingStateChanged += LoadingStateChanged;
brser.Load("other_url_here");
}
private async void LoadingStateChanged(object sender, LoadingStateChangedEventArgs e)
{
//... Omitted Code ...
Context.LogInfo("[LOG]\t----");
frame = brser.GetBrowser().GetFrame("iframe1");
if(frame == null)
{
Context.LogInfo("[LOG]\tiframe1 is null. return");
return;
}
int nretry = 100;
try
{
while (nretry > 0)
{
html = await Task.Run(frame.GetSourceAsync);
if (html.Contains("<ul class=\"some_class_to_be_loaded\">"))
{
break;
}
nretry--;
Thread.Sleep(100);
}
if (nretry == 0)
{
MessageBox.Show("Connection Error");
try
{
main_thread.Abort();
return;
}
catch (Exception ex)
{
return;
}
}
}
catch
{
return;
}
}
But it does not work. I debugged it. But when the thread sleeps, the page loading sleeps too. As a result, waiting 'loading complete event' failed. Please help me.
You can wrap your waiting part by delegate.
Like this.
Invoke(new Action(async delegate ()
{
//waiting code
int nretry = 100;
while (nretry > 0){
//...
Thread.Sleep(100);
}
}

function calling sequence disturbed due to exception

It may sound very basic but I am stuck in a situation where the function calling sequence is being disturbed due to exception even after exception handling.
I have the following situation in my windows form project (C#) (dummy code only):
private void timer1_Tick(object sender, EventArgs e)
{
try
{
BAL objBAL = new BAL();
objBAL.BL_Function1();
objBAL.BL_Function2();
objBAL.BL_Function3();
objBAL.BL_Function4();
}
catch (Exception ex)
{
MessageBox.Show(ex.Message);
}
}
the above functions are called from the business logic(BL) class which further has function callings of various functions of Data Access Layer (DAL) class.
Now the problem is whenever exception comes in any of the above functions, let's say BL_Function3(), it resets the calling to BL_Function1() which leaves BL_Function4() uncalled, which is not desirable.
My question is:
Is there any way to persists the calling sequence, i.e., if exception occurs at BL_Function2(), it should go ahead and call BL_Function3() and BL_Function4(), and then return back to BL_Function1() in the next timer_tick ?
Any help on this would be appreciated.
You can wrap each method into try..catch:
private void timer1_Tick(object sender, EventArgs e) {
//TODO: you may want to stop timer here...
BAL objBAL = new BAL();
try {
objBAL.BL_Function1();
}
catch (Exception ex) { //TODO: catch more specific exception (not Exception)
// If BL_Function1() fails, show message...
MessageBox.Show(ex.Message);
}
// ...and go ahead
try {
objBAL.BL_Function2();
}
catch (Exception ex) {
MessageBox.Show(ex.Message);
}
try {
objBAL.BL_Function3();
}
catch (Exception ex) {
MessageBox.Show(ex.Message);
}
try {
objBAL.BL_Function4();
}
catch (Exception ex) {
MessageBox.Show(ex.Message);
}
//...and restart the timer here
}
Edit: please note, that the timer keep on ticking when MessageBox is on the screen. You may want to stop the timer for a while and then restart it:
private void timer1_Tick(object sender, EventArgs e) {
// Stop the timer until execution is complete
timer1.Enabled = false;
try {
//Put all the executions here
...
}
finally {
// execution is complete (with or without exceptions), let's restart the timer
timer1.Enabled = true;
}
}
You could use an array to make it cleaner
private void timer1_Tick(object sender, EventArgs e)
{
var objBAL = new BAL();
Action[] functions = { objBAL.BL_Function1, objBAL.BL_Function2, objBAL.BL_Function3, objBAL.BL_Function3 };
foreach (var fun in functions)
{
var funCopy = fun;
try
{
funCopy ();
}
catch (Exception ex)
{
MessageBox.Show(ex.Message);
}
}
}

C# How to catch exception in a Task without block UI using wait

I have this code in a button click
private async void btnStart_Click(object sender, EventArgs e)
{
Msg.Clear();
stopWatch.Reset();
timer.Start();
stopWatch.Start();
lblTime.Text = stopWatch.Elapsed.TotalSeconds.ToString("#");
progressBar.MarqueeAnimationSpeed = 30;
try
{
await Task.Factory.StartNew(() =>
{
try
{
Reprocess();
}
catch (Exception ex)
{
Msg.Add(new clsMSG(ex.Message, "Error", DateTime.Now));
timer.Stop();
stopWatch.Stop();
throw;
}
});
}
catch
{
throw;
}
}
and this on the Reprocess method
private void Reprocess()
{
try
{
clsReprocess reprocess = new clsReprocess(tbBD.Text, dtpStart.Value, 50000);
reprocess.Start(reprocess.BD);
}
catch
{
throw;
}
}
when the Reprocess method fails, the Task goes to catch, but the throw fails (the throw inside catch (Exception ex)) and the UI blocks until the reprocess.Start method is completed.
I have two questions:
First: How can I catch the throw in the catch of my button?
Second: How can I prevent the UI blocks?
I hope you can understand me, sorry for my bad english.
You should not use Task.Factory.StartNew; Task.Run is both safer and shorter to write.
Also, you can only access UI controls from the UI thread. This may be the cause of the problems you're seeing, if Msg is data-bound to the UI. Even if it's not, you don't want to access unprotected collections (e.g., List<clsMSG>) from multiple threads.
Applying both of these guidelines reduces the code to:
private async void btnStart_Click(object sender, EventArgs e)
{
Msg.Clear();
stopWatch.Reset();
timer.Start();
stopWatch.Start();
lblTime.Text = stopWatch.Elapsed.TotalSeconds.ToString("#");
progressBar.MarqueeAnimationSpeed = 30;
try
{
await Task.Run(() => Reprocess());
}
catch (Exception ex)
{
Msg.Add(new clsMSG(ex.Message, "Error", DateTime.Now));
timer.Stop();
stopWatch.Stop();
throw;
}
}
If Reprocess throws an exception, that exception will be placed on the task returned from Task.Run. When your code awaits that task, that exception is re-raised and caught in the catch. At the end of the catch, the code will re-raise that exception (throw;).

Downloading multiple files

First of all, sorry for my English :(.
Hi, I've this code to download multiple files at once, but it's very glitchy when I'm downloading small files. If I lets say download a file that's 80 KB, then the label where I display the progress is spacing out :(.
This is the code I have right now:
bgwrkSplash.ReportProgress(44, 44444444444444);
ChangeText(lblStatus, "Downloading files to temp directory...", Color.Black);
DownloadFile();
resetEvent.WaitOne();
#region Download Handler
private void DownloadFile()
{
if (_downloadUrls.Any())
{
_intCurrentProgressValue = prgSplashStatus.Value;
_client.DownloadProgressChanged += client_DownloadProgressChanged;
_client.DownloadFileCompleted += client_DownloadFileCompleted;
var url = _downloadUrls.Dequeue();
var uri = new Uri(url);
_strFileName = Path.GetFileName(uri.LocalPath);
_client.DownloadFileAsync(new Uri(url), _strTempLocation + _strFileName);
}
}
private void client_DownloadProgressChanged(object sender, DownloadProgressChangedEventArgs e)
{
try
{
_byteCountFormatter.Add(new ByteCountFormatter {DataSize = e.BytesReceived, Time = DateTime.Now});
_byteCountFormatter = _byteCountFormatter.Skip(Math.Min(0, _byteCountFormatter.Count - 6)).ToList();
var speed = (_byteCountFormatter.Last().DataSize - _byteCountFormatter.First().DataSize)/
(_byteCountFormatter.Last().Time - _byteCountFormatter.First().Time).TotalSeconds;
var timeRemaining = TimeSpan.FromSeconds((e.TotalBytesToReceive - e.BytesReceived)/speed);
ChangeText(lblStatus, string.Format(
"Downloading {0} - {1} - {2} of {3} ({4})",
_strFileName,
ByteCountFormatter.FormatTime(timeRemaining),
ByteCountFormatter.FormatDataSize(e.BytesReceived),
ByteCountFormatter.FormatDataSize(e.TotalBytesToReceive),
ByteCountFormatter.FormatDataSpeed(speed)), Color.Black);
ChangeProgress(prgSplashStatus, e.ProgressPercentage);
}
catch (Exception exception)
{
Console.WriteLine(exception);
}
}
private void client_DownloadFileCompleted(object sender, AsyncCompletedEventArgs e)
{
try
{
try
{
if (e.Error != null)
{
throw e.Error;
}
if (e.Cancelled)
{
}
DownloadFile();
}
catch (Exception exception)
{
Console.WriteLine(exception);
}
if (!_client.IsBusy)
{
ChangeProgress(prgSplashStatus, _intCurrentProgressValue);
resetEvent.Set();
}
}
catch (Exception exception)
{
Console.WriteLine(exception);
}
}
#endregion
I've removed the Time Remaining part and it all goes smoothly now, thanks all!

Cancelling a background worker which is continuously reading from a network stream

I have a TCP server running which spits out messages of 2 bytes at regular intervals.
I'm trying to create a client side form which connects to the server and continuously reads from the stream until I click a disconnect button on the form.
So far the client works fine except that I cannot disconnect. I set the CancellationPending to true but it seems to reset back to false before the dowork method gets a chance to set e.Cancel.
I'm also sure there must be a more acceptable way of continuously reading the stream and writing to the form - at the moment I am calling RunWorkerAsync within the Worker Completed method to achieve the loop!
private void Disconnect()
{
commsWorker1.CancelAsync();
}
private void ReadFromStream()
{
try
{
commsWorker1.RunWorkerAsync();
}
catch (Exception ex)
{
writeToBox("Error: " + ex.Message);
}
}
//background worker dowork method
private void BackGroundGetServerData(object sender, DoWorkEventArgs e)
{
if (true == commsWorker1.CancellationPending)
{
e.Cancel = true;
}
else
{
Byte[] dataArray = new Byte[2];
try
{
_DataStream.Read(dataArray, 0, 2);
String reply = System.Text.Encoding.ASCII.GetString(dataArray);
e.Result = reply;
}
catch (Exception ex)
{
}
}
}
//background worker workercompleted method
private void BackGroundDisplayMessages(object sender, RunWorkerCompletedEventArgs e)
{
if (e.Cancelled)
{
//close connection here
}
else
{
writeToBox((String)e.Result);
commsWorker1.RunWorkerAsync();
}
}
}
}
Can't you just loop inside the background worker method?
private void BackGroundGetServerData(object sender, DoWorkEventArgs e)
{
while(true)
{
Byte[] dataArray = new Byte[2];
try
{
_DataStream.Read(dataArray, 0, 2);
String reply = System.Text.Encoding.ASCII.GetString(dataArray);
e.Result = reply;
}
catch (Exception ex)
{
return;
}
}
}
Then upon disconnect simply close the socket. This will cause the Exception to be thrown in the while loop and you can exit gracefully through the catch block.
Edit: Then you can update the GUI from the loop after each message is read. Make sure the handle to the control you are updating is available (assuming it's called box):
delegate void updateDelegate(String p);
private void BackGroundGetServerData(object sender, DoWorkEventArgs e)
{
while(true)
{
Byte[] dataArray = new Byte[2];
try
{
_DataStream.Read(dataArray, 0, 2);
String reply = System.Text.Encoding.ASCII.GetString(dataArray);
box.BeginInvoke(new updateDelegate(writeToBox), reply);
}
catch (Exception ex)
{
return;
}
}
}
BeginInvoke is required in this case because you are trying to update the GUI from another thread, which is not allowed. This method forwards the update to the GUI thread.
It seems that you are invoking RunWorkerAsync() in the worker complete method and that resets your CancellationPending prop. I think you can try to fix this by adding to Disconnect() method some disconnectFlag = true; and in WorkerComplete method you should add:
if (e.Cancelled || disconnectFlag)
{
disconnectFlag = false;
//close connection here
} else ...

Categories