In addition to Weibo, there is also WeChat
Please pay attention
WeChat public account
Shulou
2025-01-18 Update From: SLTechnology News&Howtos shulou NAV: SLTechnology News&Howtos > Development >
Share
Shulou(Shulou.com)06/01 Report--
In this article, the editor introduces "async and await case analysis" in detail, with detailed content, clear steps and proper handling of details. I hope this "async and await case analysis" article can help you solve your doubts.
Create static void Main () {new Thread (Go). Start (); / / Task.Factory.StartNew (Go) that has existed since .NET 1.0; / / .NET 4.0 introduced TPL Task.Run (new Action (Go)); / / .NET 4.5 added a Run method} public static void Go () {Console.WriteLine ("I am another thread");}
It is important to note that after creating an instance of Thread, you need to manually call its Start method to start it. But for Task, both StartNew and Run create a new thread and start it immediately.
Thread pool
Thread creation is a resource-intensive thing. NET provides us with thread pools to help us create and manage threads. Task uses thread pools directly by default, but Thread does not. If we don't use Task and want to use thread pooling, we can use the ThreadPool class.
Static void Main () {Console.WriteLine ("I am the main thread: ThreadId {0}", Thread.CurrentThread.ManagedThreadId); ThreadPool.QueueUserWorkItem (Go); Console.ReadLine ();} public static void Go (object data) {Console.WriteLine ("I am another thread: ThreadId {0}", Thread.CurrentThread.ManagedThreadId);}
Before passing in the parameter static void Main () {new Thread (Go) .start ("arg1"); / / before there is no anonymous delegate, we can only pass in an object parameter new Thread (delegate () {/ / after we have an anonymous delegate. GoGoGo ("arg1", "arg2", "arg3");}); new Thread () = > {/ / of course, there is also Lambada GoGoGo ("arg1", "arg2", "arg3");}) .Start (); Task.Run () = > {/ / Task is so flexible because of Lambda. GoGoGo ("arg1", "arg2", "arg3");} public static void Go (object name) {/ / TODO} public static void GoGoGo (string arg1, string arg2, string arg3) {/ / TODO} return value
Thead cannot return a value, but as a more advanced Task, you certainly have to make up for this functionality.
Static void Main () {/ / GetDayOfThisWeek runs in another thread var dayName = Task.Run (() = > {return GetDayOfThisWeek ();}); Console.WriteLine ("Today is: {0}", dayName.Result);} share data
With the parameters and return values mentioned above, let's take a look at the problem of sharing data between threads.
Private static bool _ isDone = false; static void Main () {new Thread (Done). Start (); new Thread (Done). Start ();} static void Done () {if (! _ isDone) {_ isDone = true / / when the second thread comes, it will not be executed (not absolutely, depending on the number of CPU on the computer and the running condition at that time) Console.WriteLine ("Done");}}
Data can be shared between threads through the static variable.
Thread safety
Let's first make a small adjustment to the above code to see what thread safety is. We reversed the two sentences in the Done method.
Private static bool _ isDone = false; static void Main () {new Thread (Done). Start (); new Thread (Done). Start (); Console.ReadLine ();} static void Done () {if (! _ isDone) {Console.WriteLine ("Done"); / / guess how many times this will be executed? _ isDone = true;}}
This won't happen forever, but if you're lucky, you'll win the lottery. Because the second thread comes in before * has time to set _ isDone to true, and this is not the result we want. Under multiple threads, the result is not our expected result, which means that the thread is not safe.
Lock
To solve the problems encountered above, we need to use locks. The types of locks include exclusive locks, mutexes, read-write locks, and so on. We will briefly demonstrate exclusive locks here.
Private static bool _ isDone = false; private static object _ lock = new object (); static void Main () {new Thread (Done). Start (); new Thread (Done). Start (); Console.ReadLine ();} static void Done () {lock (_ lock) {if (! _ isDone) {Console.WriteLine ("Done"); / / guess how many times this will be executed? _ isDone = true;}
After we add the lock, the locked code can only be accessed by one thread at a time, other threads will be blocked, and only after the lock is released can other threads execute the locked code.
Semaphore semaphore
I really don't know how to translate this word. From the official explanation, we can understand it this way. It can control the number of threads accessing a piece of code or a resource, beyond which other threads have to wait until now that a thread is released before the following thread can access it. This is similar to the lock, but not exclusive, it allows a certain number of threads to access it at the same time.
Static SemaphoreSlim _ sem = new SemaphoreSlim (3); / / We limit the number of threads that can be accessed simultaneously is 3 static void Main () {for (int I = 1; I {Go ();}); task.Wait () / / after calling this sentence, the main thread can catch the exception in the task / / for the Task with the return value, we do not need to call the Wait method after we receive the return value. We can also catch the exception in var task2 = Task.Run (() = > {return GetName ();}); var name = task2.Result } catch (Exception ex) {Console.WriteLine ("Exception!");}} static void Go () {throw null;} static string GetName () {throw null;} A small example to know async & awaitstatic void Main (string [] args) {Test () / / this method is actually superfluous. We could have written the following method / / await GetName () / / directly, but since the console entry method does not support async, we cannot use await Console.WriteLine ("CurrentThread Id: {0}", Thread.CurrentThread.ManagedThreadId) in the entry method. } static async Task Test () {/ / method typed async keyword, you can use await to call the same method with async / / the following method will execute await GetName () in another thread;} static async Task GetName () {/ / Delay method comes from .net 4.5 await Task.Delay (1000) / / after the return value is preceded by async, await can be used in the method Console.WriteLine ("CurrentThread Id: {0}", Thread.CurrentThread.ManagedThreadId); Console.WriteLine ("In antoher thread.");}
The original form of await
Order of execution after await
Thanks to locus's correction, await does not start new threads later (await never starts new threads), so there is a bit of a problem with the figure above.
Await will not start a new thread, and the current thread will go down until it encounters a real Async method (such as HttpClient.GetStringAsync), which internally uses Task.Run or Task.Factory.StartNew to open the thread. That is, if the method is not the Async method provided to us by .NET, we need to create our own Task before we actually create threads.
Static void Main (string [] args) {Console.WriteLine ("Main ThreadId: {0}\ r\ n", Thread.CurrentThread.ManagedThreadId); Test (); Console.ReadLine ();} static async Task Test () {Console.WriteLine ("Before calling GetName, ThreadId: {0}\ r\ n", Thread.CurrentThread.ManagedThreadId); var name = GetName () / / We don't use await here, so the following code can continue to execute / / but if the above is await GetName (), the following code will not be executed immediately, and the output will be different. Console.WriteLine ("End calling GetName.\ r\ n"); Console.WriteLine ("Get result from GetName: {0}", await name);} static async Task GetName () {/ / here is also the main thread Console.WriteLine ("Before calling Task.Run, current thread Id is: {0}", Thread.CurrentThread.ManagedThreadId); return await Task.Run () = > {Thread.Sleep (1000) Console.WriteLine ("'GetName' ThreadId: {0}", Thread.CurrentThread.ManagedThreadId); return "Jesse";};}
Let's take a look at that picture again:
Enter the main thread to start execution
Call the async method and return a Task. Notice that another thread is already running, that is, the Task in the GetName is already working.
The main thread continues to go down
Step 3 and step 4 are carried out at the same time, and the main thread is not suspended.
If another thread has finished executing, name.IsCompleted=true, the main thread still does not have to suspend, just take the result. If another thread also has the same execution completed, name.IsCompleted=false, then the main thread will suspend waiting until the result is returned.
Can only the async method be await before it is called?
Static void Main () {Test (); Console.ReadLine ();} static async void Test () {Task task = Task.Run (() = > {Thread.Sleep (5000); return "Hello World";}); string str = await task; / / 5 seconds before Console.WriteLine (str) is executed here;}
The answer is clear: await is not for async methods, but for the Task returned to us by async methods, which is why all async methods must return to us Task. So we can also add the await keyword before Task, which actually tells the compiler that I need to wait for the return value of the Task or wait for the Task to finish before I can go down.
Without the await keyword, how can I confirm that the Task execution is complete?
Static void Main () {var task = Task.Run (() = > {return GetName ();}); task.GetAwaiter () .OnCompleted (() = > {/ / 2 seconds before execution here var name = task.Result; Console.WriteLine ("My name is:" + name);}); Console.WriteLine ("main thread completed") Console.ReadLine ();} static string GetName () {Console.WriteLine ("another thread is getting a name"); Thread.Sleep (2000); return "Jesse";}
What is the difference between Task.GetAwaiter () and await Task?
After adding the await keyword, the following code will be suspended and wait until there is a return value after task execution, during which time the main thread will be suspended.
The GetAwaiter method returns an object of awaitable (inheriting the INotifyCompletion.OnCompleted method). We just pass a delegate in, and the delegate will be executed when the task is finished, but it will not affect the main thread. The following code will be executed immediately. This is why the sentence in our result will be "main thread execution completed"!
How does Task suspend the main thread waiting?
The right above belongs to the case where the main thread is not suspended, which is still a little different from our await, so how to suspend the main thread before getting the result of Task?
Static void Main () {var task = Task.Run (() = > {return GetName ();}); var name = task.GetAwaiter (). GetResult (); Console.WriteLine ("My name is: {0}", name); Console.WriteLine ("main thread completed"); Console.ReadLine () } static string GetName () {Console.WriteLine ("another thread is getting a name"); Thread.Sleep (2000); return "Jesse";}
The Task.GetAwait () method returns an object of awaitable, and the main thread is suspended by calling the object's GetResult method, but not in all cases. Remember the features of our Task? At the very beginning, another thread is started to execute the Task. When we call its result, if the Task has been executed, the main thread does not have to wait and can directly take its result. If the execution is not finished, the main thread has to suspend waiting.
Await is essentially calling the GetResult method of the awaitable object.
Static async Task Test () {Task task = Task.Run (() = > {Console.WriteLine ("another thread is running!") ; / / this sentence will only be executed once Thread.Sleep (2000); return "Hello World";}); / / here the main thread will hang and wait until the execution of task completes and we get the result var result = task.GetAwaiter () .GetResult () / / wait will not be suspended here, because the task has been executed, and we can directly get the result var result2 = await task; Console.WriteLine (str);}
After reading this, the article "async and await case Analysis" has been introduced. If you want to master the knowledge points of this article, you still need to practice and use it yourself to understand it. If you want to know more about related articles, you are welcome to follow the industry information channel.
Welcome to subscribe "Shulou Technology Information " to get latest news, interesting things and hot topics in the IT industry, and controls the hottest and latest Internet news, technology news and IT industry trends.
Views: 0
*The comments in the above article only represent the author's personal views and do not represent the views and positions of this website. If you have more insights, please feel free to contribute and share.
Continue with the installation of the previous hadoop.First, install zookooper1. Decompress zookoope
"Every 5-10 years, there's a rare product, a really special, very unusual product that's the most un
© 2024 shulou.com SLNews company. All rights reserved.