Cancel C # DoWork Desktop

C # 2008

I use the code below to enter the softphone. However, the progressive login process is a long process, since there are many things that need to be initialized and checks need to be done, I just added a few here, as this will make the code write a lot.

In the code below, I check to see if CancellationPending, if CancelAsync was called in my cancel button click event, before doing each check. It's right? Also, if the verification fails, I also call CancelAsync and set e.Cancel to true.

I would like to know if my method that I used here is the best method to use.

Thanks so much for any advice,

private void bgwProcessLogin_DoWork(object sender, DoWorkEventArgs e) { /* * Perform at test to see if the background worker has been * cancelled by the user before attemping to continue to login. * * Cancel background worker on any failed attemp to login */ // Start with cancel being false as to reset this if cancel has been set to true // in the cancel button. e.Cancel = false; NetworkingTest connection_test = new NetworkingTest(); if (!this.bgwProcessLogin.CancellationPending) { // Check local LAN or Wireless connection if (!connection_test.IsNetworkConnected()) { // Update label if (this.lblRegistering.InvokeRequired) { this.lblRegistering.Invoke(new UpdateRegisterLabelDelegate(UpdateRegisterLabel), "No network connection"); } else { this.lblRegistering.Text = "No network connection"; } // Failed attemp this.bgwProcessLogin.CancelAsync(); e.Cancel = true; return; } // Report current progress this.bgwProcessLogin.ReportProgress(0, "Network connected"); } else { // User cancelled e.Cancel = true; return; } // Test if access to Server is available if (!this.bgwProcessLogin.CancellationPending) { if (!connection_test.IsSIPServerAvailable()) { // Update label if (this.lblRegistering.InvokeRequired) { this.lblRegistering.Invoke(new UpdateRegisterLabelDelegate(UpdateRegisterLabel), "Server unavailable"); } else { this.lblRegistering.Text = "Server unavailable"; } // Failed attemp this.bgwProcessLogin.CancelAsync(); e.Cancel = true; return; } // Report current progress this.bgwProcessLogin.ReportProgress(1, "Server available"); } else { // User cancelled e.Cancel = true; return; } . . . } private void bgwProcessLogin_RunWorkerCompleted(object sender, RunWorkerCompletedEventArgs e) { // Check for any errors if (e.Error == null) { if (e.Cancelled) { // User cancelled login or login failed } else { // Login completed successfully } } else { // Something failed display error this.statusDisplay1.CallStatus = e.Error.Message; } } private void bgwProcessLogin_ProgressChanged(object sender, ProgressChangedEventArgs e) { this.lblRegistering.Text = e.UserState.ToString(); } private void btnCancel_Click(object sender, EventArgs e) { // Cancel the logging in process this.bgwProcessLogin.CancelAsync(); this.lblRegistering.Text = "Logged out"; } 
+4
source share
4 answers

Perhaps there is only one problem: if one of the DoWork event handler operations takes a long time. In this case, you can interrupt your pending operation ONLY after completion of this operation. If all operations in DoWork cannot last for a very long time (for example, no more than 5 seconds), everything will be fine, but if one of the operations can take a long time (for example, 5 minutes), in this case the user has to wait until this operation is completed.

If DoWork contains lengthy operations, you can use something like AbortableBackgroundWorker. Something like that:

 public class AbortableBackgroundWorker : BackgroundWorker { private Thread workerThread; protected override void OnDoWork(DoWorkEventArgs e) { workerThread = Thread.CurrentThread; try { base.OnDoWork(e); } catch (ThreadAbortException) { e.Cancel = true; //We must set Cancel property to true! Thread.ResetAbort(); //Prevents ThreadAbortException propagation } } public void Abort() { if (workerThread != null) { workerThread.Abort(); workerThread = null; } } } 

In this case, you can actually interrupt pending operations, but you also have some limitations (for more information about interrupting a managed thread and some restrictions, see Deposition of Depths of ThreadAbortException using a rotor ).

PS I agree with Oliver that you should wrap InvokeRequired in a more convenient way.

+8
source

You are doing it right, I suppose. You will find participants in threads that allow you to interrupt or interrupt a stream, but you do not want to use them for anything like that. It may seem strange to have all the "canceled" checks in your code, but this allows you to precisely control when you exit the stream. If you must "roughly" interrupt a worker thread, the thread will not control when it exits, and the state may be corrupted.

+1
source

In your DoWork () function, you wrote ... Depending on how many tasks of the same structure are approaching, as shown in the figure, you can reorganize this structure into your own method, indicating the changing parts as parameters.

Also this InvokeRequired if-else branch doubled the output line. A small search here on stackoverflow or on the Internet should show you a pattern for doing this doubling.

Evernything still looks good.

+1
source

There is one thing I do not need to call this.bgwProcessLogin.CancelAsync (); as you can just set this e.Cancel = true;

0
source

All Articles