In the WinForm C/S program, where the control is often updated in a child thread, the desktop program UI thread is the main thread, and an exception prompt "Access it from a thread that is not a control" appears when attempting to modify a control property directly from a child thread.
There are two common ways to update UI controls across threads:
1. Using the Invoke/begininvoke method of the control itself
2. Update using SynchronizationContext's Post/send method
1. Using the Invoke/begininvoke method of the control itself
The control class implements the ISynchronizeInvoke interface, and we look at the definition of that interface:
The Invoke method of the control class has two implementations
Object Invoke (Delegate); Executes the specified delegate on the thread that owns the underlying window handle for this control
Object Invoke (delegate,object[]);
You can see that UI controls that inherit the control class can be updated asynchronously using the Invoke method. The following code snippet implements updating the Text property of a label control in a child thread
[CSharp]View Plaincopy
- Private void Button6_click (object sender, EventArgs e)
- {
- Thread demothread =new Thread (new ThreadStart (Threadmethod));
- Demothread.isbackground = true;
- Demothread.start (); //Start thread
- }
- void Threadmethod ()
- {
- action<string> asyncuidelegate=Delegate (String N) {Label1. text=n;};/ <span style="font-family:arial, Helvetica, Sans-serif;" >/define a delegate </span>
- Label1. Invoke (Asyncuidelegate,new object[]{"Modified Label1 Text"});
- }
2. Update using SynchronizationContext's Post/send method
The SynchronizationContext class, under the System.Threading command space, provides a free-threaded context without synchronization, where the Post method is signed as follows:
public virtual void Post (SendOrPostCallback d,object State)//dispatch asynchronous message to a synchronization context
We can see that we want to update the UI control asynchronously, the first is to get the context of the UI thread, and the second is to call the Post method, and the code implements:
[CSharp]View Plaincopy
- SynchronizationContext _synccontext = null;
- Private void Button6_click (object sender, EventArgs e)
- {
- Thread demothread =new Thread (new ThreadStart (Threadmethod));
- Demothread.isbackground = true;
- Demothread.start (); //Start thread
- }
- Form Constructors
- Public Form1 ()
- {
- InitializeComponent ();
- //Get UI thread synchronization context
- _synccontext = synchronizationcontext.current;
- }
- Private void Threadmethod ()
- {
- _synccontext.post (Setlabeltext, "Revised text"); Updating UI through UI thread context in child threads
- }
- Private void Setlabeltext (object text)
- {
- This.lable1.Text = Text. ToString ();
- }
Summary of methods for updating UI controls by C # Child threads