Note that there are some explanatory texts on larger screens.

plurals
  1. PO
    primarykey
    data
    text
    <blockquote> <p>Isn't the whole point of <code>OnWorkCompleted</code> is to be called on the Main thread? Why wouldn't it work as expected?</p> </blockquote> <p>No, it's not.<br> You can't just go running any old thing on any old thread. Threads are not polite objects that you can simply say "run this, please". </p> <p>A better mental model of a thread is a freight train. Once it's going, it's off on it's own track. You can't change it's course or stop it. If you want to influence it, you either have to wait til it gets to the next train station (eg: have it manually check for some events), or derail it (<code>Thread.Abort</code> and CrossThread exceptions have much the same consequences as derailing a train... beware!).</p> <p>Winforms controls <em>sort of</em> support this behaviour (They have <code>Control.BeginInvoke</code> which lets you run any function on the UI thread), but that only works because they have a special hook into the windows UI message pump and write some special handlers. To go with the above analogy, their train checks in at the station and looks for new directions periodically, and you can use that facility to post it your own directions.</p> <p>The <code>BackgroundWorker</code> is designed to be general purpose (it can't be tied to the windows GUI) so it can't use the windows <code>Control.BeginInvoke</code> features. It has to assume that your main thread is an unstoppable 'train' doing it's own thing, so the completed event has to run in the worker thread or not at all.</p> <p>However, as you're using winforms, in your <code>OnWorkCompleted</code> handler, you can get the Window to execute <em>another</em> callback using the <code>BeginInvoke</code> functionality I mentioned above. Like this:</p> <pre><code>// Assume we're running in a windows forms button click so we have access to the // form object in the "this" variable. void OnButton_Click(object sender, EventArgs e ) var b = new BackgroundWorker(); b.DoWork += ... blah blah // attach an anonymous function to the completed event. // when this function fires in the worker thread, it will ask the form (this) // to execute the WorkCompleteCallback on the UI thread. // when the form has some spare time, it will run your function, and // you can do all the stuff that you want b.RunWorkerCompleted += (s, e) { this.BeginInvoke(WorkCompleteCallback); } b.RunWorkerAsync(); // GO! } void WorkCompleteCallback() { Button.Enabled = false; //other stuff that only works in the UI thread } </code></pre> <p><a href="http://msdn.microsoft.com/en-us/library/system.componentmodel.runworkercompletedeventargs.result.aspx" rel="noreferrer">Also, don't forget this:</a></p> <blockquote> <p>Your RunWorkerCompleted event handler should always check the Error and Cancelled properties before accessing the Result property. If an exception was raised or if the operation was canceled, accessing the Result property raises an exception.</p> </blockquote>
    singulars
    1. This table or related slice is empty.
    plurals
    1. This table or related slice is empty.
    1. This table or related slice is empty.
    1. This table or related slice is empty.
    1. This table or related slice is empty.
    1. VO
      singulars
      1. This table or related slice is empty.
    2. VO
      singulars
      1. This table or related slice is empty.
    3. VO
      singulars
      1. This table or related slice is empty.
 

Querying!

 
Guidance

SQuiL has stopped working due to an internal error.

If you are curious you may find further information in the browser console, which is accessible through the devtools (F12).

Reload