. Net provides many multi-threaded programming tools, probably because there are too many tools, so there is always a headache to grasp. Here I will talk about some of my multi-threaded programming experience, I hope to help you.
You do not need to pass parameters or return parameters.
We know that the most intuitive way to start a Thread is to use the Thread class. The specific steps are as follows:
ThreadStart threadStart = new ThreadStart (Calculate );
Thread thread = new Thread (threadStart );
Thread. Start ();
Public void Calculate (){
Double Diameter = 0.5;
Console. Write ("The perimeter Of Circle with a Diameter of {0} is {1}" Diameter, Diameter * Math. PI );
}
Example 1
We have defined a ThreadStart type delegate as above. This delegate develops the method to be executed by the thread: Calculate, in which the circumference of a circle with a diameter of 0.5 is calculated, and output. this constitutes the simplest example of multithreading. In many cases, this is enough, and the ThreadStart delegate is defined as void ThreadStart (), that is, the method to be executed does not have parameters. This is obviously a huge deficiency. To make up for this defect, a smart programmer has come up with many good methods, we will introduce it in the section that needs to pass multiple parameters. Here we will first introduce it. net another delegate set to solve this problem: ParameterizedThreadStart, which will be detailed below
A single parameter needs to be passed
ParameterThreadStart is defined as void ParameterizedThreadStart (object state )?? The startup function of the thread defined by this delegate can accept an input parameter. The example is as follows:
ParameterizedThreadStart threadStart = new ParameterizedThreadStart (Calculate)
Thread thread = new Thread ()
Thread. Start (0.9 );
Public void Calculate (object arg ){
Double Diameter = double (arg );
Console. Write ("The perimeter Of Circle with a Diameter of {0} is {1}" Diameter, Diameter * Math. PI );
}
Example 2
The Calculate method has a parameter of the object type. Although there is only one parameter and it is of the object type, type conversion is still required when using it, but fortunately there is a parameter, in addition, by combining multiple parameters into a class, and passing the instance of this class as a parameter, multiple parameters can be passed.
Multiple parameters need to be passed
Although multiple parameters can be transferred by entrusting ParameterizedThreadStart by encapsulating the required parameters into a class, the parameter conversion is inevitable because the input parameter of this delegate is an object, there are several common parameter passing methods below. Let's take a look at them one by one.
Use special thread classes
This is a classic mode that many programmers love to use. Simply put, they put the methods that need to be executed by another thread and the parameters they need into a class, and the parameters are used as the attributes of the class, declare the instance during the call, and then initialize the attributes. When the method is executed, use the initialized attributes in the class for execution, so that the method itself does not need parameters, the multi-parameter transfer effect is achieved, so we can use the ThreadStart delegation without parameters mentioned at the beginning of this article, and because the methods and parameters to be executed are put in a class, fully embodies the characteristics of object-oriented. the procedure is as follows:
We use a class to package the method for calculating the area. The input parameter Diameter (Diameter) is a field of this class.
Public class MyThread
{
Public double Diameter = 10;
Public double Result = 0;
Public MyThread (int Diameter)
{
This. Diameter = Diameter;
}
Public void Calculate ()
{
Console. WriteLine ("Calculate Start ");
Thread. Sleep (2000 );
Result = Diameter * Math. PI ;;
Console. WriteLine ("Calculate End, Diameter is {0}, Result is {1}", this. Diameter, Result );
}
}
MyThread t = new MyThread (5.0 );
ThreadStart threadStart = new ThreadStart (t. Calculate)
Thread thread = new Thread (threadStart );
Thread. Start ();
Example 3
In this way, the parameter transfer is changed to attribute sharing. It is good to encapsulate the data involved in the logic and the logic in terms of encapsulation, this method also has a clever variant that uses the anonymous method. This variant can be used to save independent classes. Now I am giving this method.
Double Diameter = 6;
Double Result = 0;
Thread ta = new Thread (new ThreadStart (delegate ()
{
Thread. Sleep (2000 );
Result = Diameter * Math. PI;
Console. WriteLine ("anonymous Calculate End, Diameter is {0}, Result is {1}", Diameter, Result );;
}));
Ta. Start ();
Example 4
This method is the same as in the preceding example. It changes the parameter transfer to the call to the variable, thus canceling the parameter transfer. However, the latter makes full use of a property of the anonymous method, you can directly use local variables in the current context, such as Diameter in the delegate, and Result. of course, the disadvantage of doing so is that if the anonymous method is too long, the program's readability will be reduced, so few people usually do this. Here we will provide this method for your reference, for more information about anonymous delegation, see
Smart readers must think that, since fields can be used to input variables, you can also use fields to output variables, for example, in the above two examples, we can see that the calculation results are written into a variable named Result (highlighted). Can we directly access this variable to get the calculation Result?
In this case, there is a fatal problem: Since it is asynchronous execution, how does the main thread know when the split thread completes the calculation? For example, in the above two examples, our threads are sleeping for 2000 milliseconds before calculation. If the main thread accesses the Result before the computation is completed, only one 0 value can be obtained. so we have a series of solutions below.
Parameters need to be passed and return parameters
As mentioned earlier, the main Thread needs to know when the sub-Thread will be executed. You can use the Thread. ThreadState enumeration to determine when the sub-Thread will be executed.
When the ThreadState of the thread is = ThreadState. when you Stop the job, it usually means that the thread has finished the job and the result is available. If it is not in this status, continue to execute other jobs, or wait for a while and try again. if we need to wait for multiple subthreads to return data and use their results for asynchronous computing, it is called thread synchronization, next, we will introduce another method that I recommend. It can customize the number of parameters and return data, which is relatively convenient to use.
Use delegate asynchronous call methods and callbacks
First, we need to define the method to be called asynchronously as a delegate, and then use BeginInvoke for asynchronous call. The first parameter of BeginInvoke is the diameter, the second is the method called after the thread is executed.
Delegate double CalculateMethod (double Diameter );
Static CalculateMethod calcMethod;
Double result = 0;
Static void Main (string [] args)
{
CalcMethod = new CalculateMethod (Calculate );
CalcMethod. BeginInvoke (5, new AsyncCallback (TaskFinished), null );
}
/// <Summary>
/// The function called by the thread
/// <Summary>
Public static double Calculate (double Diameter)
{
Return Diameter * Math. PI;
}
/// <Summary>
/// The callback function after the thread is completed
/// <Summary>
Public static void TaskFinished (IAsyncResult result)
{
Result = calcMethod. EndInvoke (result );
}