Many times, writing Windows programs requires combining multi-threading, and using the following code in C# to create and start a new thread.
Thread thread = new Thread(new ThreadStart(ThreadProc));//Instantiate a thread
= true;//Change thread to background thread
();//Open thread
But many times, in new threads, we need to interact with the UI (Windows Form Designer User Interface), which is not allowed to do directly in C#. Refer to the description in MSDN.
Windows Forms uses the single-threaded unit (STA) model because Windows Forms is based on native Win32 windows, which are essentially unit threads. The STA model means that windows can be created on any thread, but once created, the window cannot switch threads, and all function calls to it must occur on its creation thread. In addition to Windows Forms, classes in the .NET Framework use the free threading model.
The STA model requires that any method on a control that needs to be called from a control's non-creation thread must be marshaled to (executed on) the creation thread of the control. The base class Control provides several methods for this purpose (Invoke, BeginInvoke, and EndInvoke). Invoke generates synchronous method calls; BeginInvoke generates asynchronous method calls.
Controls in Windows forms are bound to specific threads and are not thread-safe. Therefore, if the control's method is called from another thread, one of the control's Invoke methods must be used to marshall the call to the appropriate thread.
As you can see, the Invoke method must be called, and BeginInvoke can be considered an asynchronous version of Invoke. The call method is as follows:
public delegate void OutDelegate(string text); public void OutText(string text) { (text); ( "\t\n" ); } OutDelegate outdelegate = new OutDelegate( OutText ); (outdelegate, new object[]{text});
If you need to operate on the UI in another thread, you need a function similar to OutText, and a delegate delegate for the function. Of course, what is shown here is custom.
This property can be used to determine whether the Invoke method must be called, which is useful when you don't know which thread has the control.
In other words, by judging InvokeRequired, you can know whether you need to use delegates to call some methods of the current control. In this way, you can modify the OutText function:
public delegate void OutDelegate(string text); public void OutText(string text) { if( ) { OutDelegate outdelegate = new OutDelegate( OutText ); (outdelegate, new object[]{text}); return; } (text); ( "\t\n" ); }
Note that the function here does not return. If there is a return, you need to call Invoke or EndInvoke to obtain the returned result. Don't lose the return value because of the wrapper. If the call is not completed, both Invoke and EndInvoke will cause blockage.
Now if I have a thread function like this:
public void ThreadProc() { for(int i = 0; i < 5; i++) { OutText( () ); (1000); } }
If the loops are very large or it misses (1000); then your UI will definitely stop responding. Want to know the reason? Look at the object in front of BeginInvoke. That's right, it is this, that is, the main thread. When your main thread keeps calling OutText, the UI will of course stop responding.
In the past, creating a new thread in VC requires calling the AfxBeginThread function. The first parameter in this function is the address of the thread function, and the second parameter is a pointer type of type LPVOID, which will be passed to the thread function. Now we have no way to use this method to pass parameters. We need to wrap the parameters and thread functions passed to the thread into a separate class, then initialize the parameters required by the thread in the constructor of this class, and then pass the thread function of the instance to the constructor of the Thread class. The code is roughly as follows:
public class ProcClass { private string procParameter = ""; public ProcClass(string parameter) { procParameter = parameter; } public void ThreadProc() { } } ProcClass threadProc = new ProcClass("use thread class"); Thread thread = new Thread( new ThreadStart( ) ); = true; ();
That's it, an intermediate class needs to be created to pass the parameters required by the thread.
So what should I do if my thread needs parameters and needs to interact with the UI? You can modify the code:
public class ProcClass { private string procParameter = ""; private delg = null; public ProcClass(string parameter, delg) { procParameter = parameter; = delg; } public void ThreadProc() { ("use ()", null, null); } } ProcClass threadProc = new ProcClass("use thread class", new OutDelegate(OutText)); Thread thread = new Thread( new ThreadStart( ) ); = true; ();
The above is all the content of this article. I hope it will be helpful to everyone's study and I hope everyone will support me more.