catalogue
2. Blocking method of task (Wait/WaitAll/WaitAny)
3, Asynchronous method (async/await)
1, What is asynchronous
Synchronous and asynchronous are mainly used to modify methods. When a method is called, the caller needs to wait for the method to complete execution and return to continue execution. We call this method a synchronous method; When a method is called, it returns immediately and gets a thread to execute the business inside the method. The caller does not have to wait for the method to complete execution. We call this method asynchronous method.
The advantage of asynchrony is that it is non blocking (the calling thread will not pause to wait for the sub thread to complete). Therefore, we set some time-consuming tasks that do not need to use the results immediately as asynchronous execution, which can improve the running efficiency of the program. net4.0 introduces the Task class based on ThreadPool. Microsoft strongly recommends using Task to execute asynchronous tasks. Now, Task is basically used in asynchronous methods in C# class library; net5.0 introduced async/await to make asynchronous programming more convenient. This chapter mainly introduces the contents related to Task and async/await, and other asynchronous operation methods will be introduced in the next chapter.
2, Task introduction
Task is launched on the basis of ThreadPool. Let's briefly understand ThreadPool. There are several threads in the ThreadPool. If a task needs to be processed, an idle thread will be obtained from the thread pool to execute the task. After the task is executed, the thread will not be destroyed, but recycled by the thread pool for subsequent tasks. When all threads in the thread pool are busy and there are new tasks to be processed, the thread pool will create a new thread to process the task. If the number of threads reaches the set maximum, the task will queue up and wait for other tasks to release threads before execution. Thread pool can reduce the creation of threads and save overhead. Look at the chestnut of ThreadPool
static void Main(string[] args) { for (int i = 1; i <=10; i++) { //ThreadPool execution task ThreadPool.QueueUserWorkItem(new WaitCallback((obj) => { Console.WriteLine($"The first{obj}Execute tasks"); }),i); } Console.ReadKey(); }
The code above performs 10 tasks through ThreadPool
Compared with threads, ThreadPool can reduce the creation of threads and effectively reduce the system overhead; However, ThreadPool cannot control the execution order of threads, nor can we obtain notifications of Thread cancellation / exception / completion in the Thread pool, that is, we cannot effectively monitor and control the threads in the Thread pool.
1 Task creation and running
We know the disadvantages of ThreadPool: we cannot control the execution order of threads in the thread pool, nor can we get the notification of thread cancellation / exception / completion in the thread pool. net4.0 introduces task on the basis of ThreadPool. Task has the advantages of thread pool and solves the disadvantages of using thread pool which is not easy to control.
First, let's take a look at how to create and run a Task. There are five ways to create and execute a Task:
static void Main(string[] args) { //1. Instantiate a Task in the new mode, which needs to be started through the Start method Task task = new Task(() => { Thread.Sleep(100); Console.WriteLine($"hello, task1 Thread ID by{Thread.CurrentThread.ManagedThreadId}"); }); task.Start(); //2. Task. Factory. Startnew (action) creates and starts a task Task task2 = Task.Factory.StartNew(() => { Thread.Sleep(100); Console.WriteLine($"hello, task2 Thread ID by{ Thread.CurrentThread.ManagedThreadId}"); }); //3. Task. Run (action) puts the task in the process pool queue, returns and starts a task Task task3 = Task.Run(() => { Thread.Sleep(100); Console.WriteLine($"hello, task3 Thread ID by{ Thread.CurrentThread.ManagedThreadId}"); }); Console.WriteLine("Execute main thread!"); Console.ReadKey(); //4. Start a new thread and specify the work method Task.Factory.StartNew(Work); static void Work() { _running = true; while (_running) { //SendOut(); //DealWith(); Thread.Sleep(50); } } //5. This method can also call UI controls across threads Action action = () => { UiManager.SurfaceForm.SetSurplusPhotoNumber(count1.ToString()); }; Task.Factory.StartNew(action); }
We see that "execute main thread" is printed first, and then each Task is printed, which shows that the Task will not block the UI main thread. None of the chestnuts above have a return value. We can also create a Task < tresult > with a return value. The usage is basically the same as that without a return value. Let's simply modify the chestnuts above. The code is as follows:
static void Main(string[] args) { 1.new Instantiate a Task,Need to pass Start Method start Task<string> task = new Task<string>(() => { return $"hello, task1 of ID by{Thread.CurrentThread.ManagedThreadId}"; }); task.Start(); 2.Task.Factory.StartNew(Func func)Create and start a Task Task<string> task2 =Task.Factory.StartNew<string>(() => { return $"hello, task2 of ID by{ Thread.CurrentThread.ManagedThreadId}"; }); 3.Task.Run(Func func)Put the task in the process pool queue, return and start a Task Task<string> task3= Task.Run<string>(() => { return $"hello, task3 of ID by{ Thread.CurrentThread.ManagedThreadId}"; }); Console.WriteLine("Execute main thread!"); Console.WriteLine(task.Result);//Pay attention to task Result blocks the UI main thread when getting results Console.WriteLine(task2.Result); Console.WriteLine(task3.Result); Console.ReadKey(); }
Pay attention to task When resut obtains the Result, it will block the UI main thread. That is, if the task is not completed, it will wait for the task to complete execution, obtain the Result, and then execute the following code
2. Blocking method of task (Wait/WaitAll/WaitAny)
1. Thread blocking method
When using Thread, we know to use Thread The join () method blocks the UI main Thread. Take an example:
static void Main(string[] args) { Thread th1 = new Thread(() => { Thread.Sleep(500); Console.WriteLine("Thread 1 execution completed!"); }); th1.Start(); Thread th2 = new Thread(() => { Thread.Sleep(1000); Console.WriteLine("Thread 2 execution completed!"); }); th2.Start(); //Blocking UI main thread th1.Join(); th2.Join(); Console.WriteLine("Main thread execution completed!"); Console.ReadKey(); }
2. Wait/WaitAny/WaitAll method of task
Thread's Join method can block the calling thread, but it has some disadvantages: ① if we want to block many threads, each thread must call the Join method once; ② If we want to unblock all threads (or any thread) immediately, it is not easy to use the Join method. Task provides the , Wait/WaitAny/WaitAll , method, which makes it easier to control thread blocking.
task.Wait() means to wait for the task to finish executing (which will block the UI main thread), and its function is similar to thead Join(); Task.WaitAll(Task[] tasks) means that only all tasks are executed and unblocked; Task.WaitAny(Task[] tasks) indicates that as long as one task is completed, the blocking will be removed. Look at a chestnut:
static void Main(string[] args) { Task task1 = new Task(() => { Thread.Sleep(500); Console.WriteLine("Thread 1 execution completed!"); }); task1.Start(); Task task2 = new Task(() => { Thread.Sleep(1000); Console.WriteLine("Thread 2 execution completed!"); }); task2.Start(); //Block the main thread. After Task1 and task2 are executed, the main thread can be executed //The same functions can be realized by executing [task1.Wait();task2.Wait();] Task.WaitAll(new Task[]{ task1,task2}); Console.WriteLine("Main thread execution completed!"); Console.ReadKey(); }
3, Asynchronous method (async/await)
C# 5 introduces a simple method, asynchronous programming. This method makes use of NET Framework 4.5 and later NET Core 5.0 and asynchronous support in Windows runtime
Test environment: vs2019 Net Framework4.6.1.
Let's look at a chestnut:
private void button1_Click(object sender, EventArgs e) { Console.WriteLine("Main thread ManagedThreadId:" + Thread.CurrentThread.ManagedThreadId); AsyncTest(); } static async void AsyncTest() { Console.WriteLine("*******Start************ManagedThreadId:" + Thread.CurrentThread.ManagedThreadId); Task<int> taskA = Print(); Console.WriteLine("*********Middle**********ManagedThreadId:" + Thread.CurrentThread.ManagedThreadId); int a = await taskA; Console.WriteLine("return a=" + a); Console.WriteLine("*********End**********ManagedThreadId:" + Thread.CurrentThread.ManagedThreadId); } static Task<int> Print() { //Console.WriteLine("Print method starts execution") return Task<int>.Run(() => { Thread.Sleep(5000); return 98; }); }
Reference website:
https://www.cnblogs.com/wyy1234/p/9172467.html#_label1_3