Starting with an exception
In the previous article, delegate is used to construct an asynchronous operation to improve the user experience, but an exception occurs when the attributes of the UI control are operated in this asynchronous operation. In fact, using delegate to construct asynchronous operations creates a worker thread behind the scenes. This exception will be thrown if you operate on the attributes of the UI element from the thread that is not the UI creation.
However, if we do not run this program in Visual Studio, this exception will not occur. By viewing the exception StackTrace, it is found that the exception is thrown when the Control handle is obtained:
At System. Windows. Forms. Control. get_Handle ()
At System. Windows. Forms. Control. set_WindowText (String value)
At System. Windows. Forms. Control. set_Text (String value)
At System. Windows. Forms. ButtonBase. set_Text (String value)
//... Omitted...
Sacrifice Reflector to see the relevant code:
1: public IntPtr Handle
2 :{
3: get
4 :{
5: if (checkforillegalcrossthreadcils &&! InCrossThreadSafeCall) & this. InvokeRequired)
6 :{
7: throw new InvalidOperationException (SR. GetString ("IllegalCrossThreadCall", new object [] {this. Name }));
8 :}
9: if (! This. IsHandleCreated)
10 :{
11: this. CreateHandle ();
12 :}
13: return this. HandleInternal;
14 :}
15 :}
Next, check the checkforillegalcrossthreadcals, inCrossThreadSafeCall fields, and InvokeRequired. The responsibility of InvokeRequired is to determine whether the currently running thread is the same as the form main thread.
The literal meaning of checkforillegalcrossthreadcils is "whether to check cross-thread calls ". In the static constructor of Control, this field is set to checkforillegalcrossthreadcils = Debugger. isAttached.
In fact, it is normal to set the properties of the control in the thread where the control is not created to throw an exception. If multiple threads access the properties of the control, thread security issues may occur, resulting in unstable control operation. So what is the solution?
You can only set the properties of a widget in the thread where the widget is created.
Nonsense. Of course I know this is acceptable, but the two threads are running independently. What can I do to stop other threads from working and execute the tasks I have assigned, this is not two people. I can talk to him. Hey, don't you mention that the mechanism here is really like two people. Thread a sends a text message to thread B, saying, dude, I have something to handle and I am afraid of problems, you can leave it empty for me to handle it. According to the method of sending text messages by thread a, thread a is either busy with its own affairs after sending text messages and waiting for thread B to process the messages, or you have to wait until thread B finishes processing.
Control. Invoke & Control. BeginInvoke
Control. invoke and Control. beginInvoke is the method for sending text messages. If you use Control. invoke sends a text message, so thread A will be like an infatuated man, always waiting for the echo of thread B, and if Control is used. beginInvoke sends a text message. After sending the text message, thread A will be busy and wait until thread B finishes processing it.
Note: Some people may find that the BeginInvoke method has a Begin, and they may be wondering, this is an asynchronous feature. Is it like using the BeginInvoke method of delegate in the previous article to start a worker thread? Remember, BeginInvoke is an asynchronous operation, but it is not implemented through a thread. The specific method is described later.
Let's take a look at how to use Control. Invoke and Control. BeginInvoke to send text messages (to distinguish Control. BeginInvoke from delegate. BeginInvoke, always with the Control prefix:
1: /// <summary>
2: /// Assume that this is a data query method, which takes a long time.
3: /// </summary>
4: /// <Returns> returns the query result from the database </returns>
5: private