First of all, decide if you really need to use Invoke
at all. I think this is a long time ago, my opinion is that Invoke
is one of the most abusive methods for invoking an action in the user interface thread after it has been initiated from the workflow. An alternative is to create some type of message object in the workflow that describes the action that needs to be performed on the user interface thread and put it in a common queue. Then, the user interface thread will examine this queue at some interval using System.Windows.Forms.Timer
and invoke each action. This has several advantages.
- It breaks the tight connection between the user interface and the workflows that
Invoke
imposes. - He is responsible for updating the user interface thread in the user interface thread, where he must belong in any case.
- The user interface flow determines when and how often an update should occur.
- There is no risk of user interface message overflow, as would be the case with marshaling methods initiated by a workflow.
- The workflow should not wait for confirmation that the update has been completed before proceeding with the next steps (i.e. you will get more bandwidth for both the user interface and workflows).
- It is much easier to handle shutdown operations, as you can pretty much eliminate all the race conditions that are usually present when a workflow request is legitimately completed.
Of course, Invoke
very useful, and there are many reasons to continue using this approach. If you decide to continue using Invoke
, then read more.
One idea is to set the KillThreads
flags in the KillThreads
event, and then cancel closing the form by setting FormClosingEventArgs.Cancel = true
. You can inform the user of the completion of the completion of work. You can disable some controls on the form so that new actions cannot be initiated. Thus, we basically signal that a shutdown was requested, but they postpone closing the form until the workflows stop first. To do this, you can run a timer that periodically checks to see if the worker threads have completed, and if they are, you can call Form.Close
.
public class YourForm : Form { private Thread WorkerThread; private volatile bool KillThreads = false; private void YourForm_Closing(object sender, FormClosingEventArgs args) {
The code is above Join
calls, but it defines a timeout of 0, which causes the Join
call to return immediately. This should contain user interface redirection messages.
source share