Note that there are some explanatory texts on larger screens.

plurals
  1. PO
    primarykey
    data
    text
    <p>First off decide whether or not you really need to be using <code>Invoke</code> at all. It is, and has been for a while now, my opinion that <code>Invoke</code> is one of the most overused techniques for causing an action to occur on the UI thread after it has been initiated from a worker thread. An alternative is to create some type of message object in the worker thread describing the action that needs to be done on the UI thread and place it into a shared queue. The UI thread will then poll this queue on some interval using <code>System.Windows.Forms.Timer</code> and cause each action to occur. This has several advantages.</p> <ul> <li>It breaks the tight coupling between the UI and worker threads that <code>Invoke</code> imposes.</li> <li>It puts the responsibility of updating the UI thread on the UI thread where it should belong anyway.</li> <li>The UI thread gets to dictate when and how often the update should take place.</li> <li>There is no risk of the UI message pump being overrun as would be the case with the marshaling techniques initiated by the worker thread.</li> <li>The worker thread does not have to wait for an acknowledgement that the update was performed before proceeding with its next steps (ie. you get more throughput on both the UI and worker threads).</li> <li>It is a <em>lot</em> easier to handle shutdown operations since you can pretty much eliminate all race conditions that would normally be present when requesting worker threads to gracefully terminate.</li> </ul> <p>Of course, <code>Invoke</code> is very useful and there are many reasons to keep using this approach. If you do decide to keep using <code>Invoke</code> then read more.</p> <p>One idea is to set the <code>KillThreads</code> flags in the <code>Form.Closing</code> event and then cancel closing the form by setting <code>FormClosingEventArgs.Cancel = true</code>. You may want to let the user know that a shutdown has been requested and is in progress. You may want to disable some of the controls on the form so new actions cannot be initiated. So basically we are signaling that a shutdown has been requested, but are deferring the closing of the form until the worker threads have shutdown first. To do this you may want to start a timer that periodically checks to see if the worker threads have ended and if they have then you can call <code>Form.Close</code>.</p> <pre><code>public class YourForm : Form { private Thread WorkerThread; private volatile bool KillThreads = false; private void YourForm_Closing(object sender, FormClosingEventArgs args) { // Do a fast check to see if the worker thread is still running. if (!WorkerThread.Join(0)) { args.Cancel = true; // Cancel the shutdown of the form. KillThreads = true; // Signal worker thread that it should gracefully shutdown. var timer = new System.Timers.Timer(); timer.AutoReset = false; timer.SynchronizingObject = this; timer.Interval = 1000; timer.Elapsed = (sender, args) =&gt; { // Do a fast check to see if the worker thread is still running. if (WorkerThread.Join(0)) { // Reissue the form closing event. Close(); } else { // Keep restarting the timer until the worker thread ends. timer.Start(); } }; timer.Start(); } } } </code></pre> <p>The code above calls <code>Join</code>, but it specifies a timeout of 0 which causes the <code>Join</code> call to return immediately. This should keep the UI pumping messages.</p>
    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. 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