How and when to use ‘async’ and ‘await’

前端 未结 21 1792
你的背包
你的背包 2020-11-21 05:07

From my understanding one of the main things that async and await do is to make code easy to write and read - but is using them equal to spawning background threads to perfo

相关标签:
21条回答
  • 2020-11-21 05:31

    This answer aims to provide some info specific to ASP.NET.

    By utilizing async/await in MVC controller, it is possible to increase thread pool utilization and achieve a much better throughput, as explained in the below article,

    http://www.asp.net/mvc/tutorials/mvc-4/using-asynchronous-methods-in-aspnet-mvc-4

    In web applications that sees a large number of concurrent requests at start-up or has a bursty load (where concurrency increases suddenly), making these web service calls asynchronous will increase the responsiveness of your application. An asynchronous request takes the same amount of time to process as a synchronous request. For example, if a request makes a web service call that requires two seconds to complete, the request takes two seconds whether it is performed synchronously or asynchronously. However, during an asynchronous call, a thread is not blocked from responding to other requests while it waits for the first request to complete. Therefore, asynchronous requests prevent request queuing and thread pool growth when there are many concurrent requests that invoke long-running operations.

    0 讨论(0)
  • 2020-11-21 05:33

    See this fiddle https://dotnetfiddle.net/VhZdLU (and improve it if possible) for running a simple console application which shows usages of Task, Task.WaitAll(), async and await operators in the same program.

    This fiddle should clear your execution cycle concept.

    Here is the sample code

    using System;
    using System.Threading.Tasks;
    
    public class Program
    {
        public static void Main()
        {               
            var a = MyMethodAsync(); //Task started for Execution and immediately goes to Line 19 of the code. Cursor will come back as soon as await operator is met       
            Console.WriteLine("Cursor Moved to Next Line Without Waiting for MyMethodAsync() completion");
            Console.WriteLine("Now Waiting for Task to be Finished");       
            Task.WaitAll(a); //Now Waiting      
            Console.WriteLine("Exiting CommandLine");       
        }
    
        public static async Task MyMethodAsync()
        {
            Task<int> longRunningTask = LongRunningOperation();
            // independent work which doesn't need the result of LongRunningOperationAsync can be done here
            Console.WriteLine("Independent Works of now executes in MyMethodAsync()");
            //and now we call await on the task 
            int result = await longRunningTask;
            //use the result 
            Console.WriteLine("Result of LongRunningOperation() is " + result);
        }
    
        public static async Task<int> LongRunningOperation() // assume we return an int from this long running operation 
        {
            Console.WriteLine("LongRunningOperation() Started");
            await Task.Delay(2000); // 2 second delay
            Console.WriteLine("LongRunningOperation() Finished after 2 Seconds");
            return 1;
        }   
    
    }
    

    Trace coming from Output Window:

    0 讨论(0)
  • 2020-11-21 05:34

    I think you've picked a bad example with System.Threading.Thread.Sleep

    Point of an async Task is to let it execute in background without locking the main thread, such as doing a DownloadFileAsync

    System.Threading.Thread.Sleep isn't something that is "being done", it just sleeps, and therefore your next line is reached after 5 seconds ...

    Read this article, I think it is a great explanation of async and await concept: http://msdn.microsoft.com/en-us/library/vstudio/hh191443.aspx

    0 讨论(0)
  • 2020-11-21 05:34

    The answers here are useful as a general guidance about await/async. They also contain some detail about how await/async is wired. I would like to share some practical experience with you that you should know before using this design pattern.

    The term "await" is literal, so whatever thread you call it on will wait for the result of the method before continuing. On the foreground thread, this is a disaster. The foreground thread carries the burden of constructing your app, including views, view models, initial animations, and whatever else you have boot-strapped with those elements. So when you await the foreground thread, you stop the app. The user waits and waits when nothing appears to happen. This provides a negative user experience.

    You can certainly await a background thread using a variety of means:

    Device.BeginInvokeOnMainThread(async () => { await AnyAwaitableMethod(); });
    
    // Notice that we do not await the following call, 
    // as that would tie it to the foreground thread.
    try
    {
    Task.Run(async () => { await AnyAwaitableMethod(); });
    }
    catch
    {}
    

    The complete code for these remarks is at https://github.com/marcusts/xamarin-forms-annoyances. See the solution called AwaitAsyncAntipattern.sln.

    The GitHub site also provides links to a more detailed discussion on this topic.

    0 讨论(0)
  • 2020-11-21 05:36

    Showing the above explanations in action in a simple console program:

    class Program
    {
        static void Main(string[] args)
        {
            TestAsyncAwaitMethods();
            Console.WriteLine("Press any key to exit...");
            Console.ReadLine();
        }
    
        public async static void TestAsyncAwaitMethods()
        {
            await LongRunningMethod();
        }
    
        public static async Task<int> LongRunningMethod()
        {
            Console.WriteLine("Starting Long Running method...");
            await Task.Delay(5000);
            Console.WriteLine("End Long Running method...");
            return 1;
        }
    }
    

    And the output is:

    Starting Long Running method...
    Press any key to exit...
    End Long Running method...
    

    Thus,

    1. Main starts the long running method via TestAsyncAwaitMethods. That immediately returns without halting the current thread and we immediately see 'Press any key to exit' message
    2. All this while, the LongRunningMethod is running in the background. Once its completed, another thread from Threadpool picks up this context and displays the final message

    Thus, not thread is blocked.

    0 讨论(0)
  • 2020-11-21 05:36

    Async & Await Simple Explanation

    Simple Analogy

    A person may wait for their morning train. This is all they are doing as this is their primary task that they are currently performing. (synchronous programming (what you normally do!))

    Another person may await their morning train whilst they smoke a cigarette and then drink their coffee. (Asynchronous programming)

    What is asynchronous programming?

    Asynchronous programming is where a programmer will choose to run some of his code on a separate thread from the main thread of execution and then notify the main thread on it's completion.

    What does the async keyword actually do?

    Prefixing the async keyword to a method name like

    async void DoSomething(){ . . .
    

    allows the programmer to use the await keyword when calling asynchronous tasks. That's all it does.

    Why is this important?

    In a lot of software systems the main thread is reserved for operations specifically relating to the User Interface. If I am running a very complex recursive algorithm that takes 5 seconds to complete on my computer, but I am running this on the Main Thread (UI thread) When the user tries to click on anything on my application, it will appear to be frozen as my main thread has queued and is currently processing far too many operations. As a result the main thread cannot process the mouse click to run the method from the button click.

    When do you use Async and Await?

    Use the asynchronous keywords ideally when you are doing anything that doesn't involve the user interface.

    So lets say you're writing a program that allows the user to sketch on their mobile phone but every 5 seconds it is going to be checking the weather on the internet.

    We should be awaiting the call the polling calls every 5 seconds to the network to get the weather as the user of the application needs to keep interacting with the mobile touch screen to draw pretty pictures.

    How do you use Async and Await

    Following on from the example above, here is some pseudo code of how to write it:

        //ASYNCHRONOUS
        //this is called using the await keyword every 5 seconds from a polling timer or something.
    
        async Task CheckWeather()
        {
            var weather = await GetWeather();
            //do something with the weather now you have it
        }
    
        async Task<WeatherResult> GetWeather()
        {
    
            var weatherJson = await CallToNetworkAddressToGetWeather();
            return deserializeJson<weatherJson>(weatherJson);
        }
    
        //SYNCHRONOUS
        //This method is called whenever the screen is pressed
        void ScreenPressed()
        {
            DrawSketchOnScreen();
        }
    

    Additional Notes - Update

    I forgot to mention in my original notes that in C# you can only await methods that are wrapped in Tasks. for example you may await this method:

    // awaiting this will return a string.
    // calling this without await (synchronously) will result in a Task<string> object.
    async Task<string> FetchHelloWorld() {..
    

    You cannot await methods that are not tasks like this:

    async string FetchHelloWorld() {..
    

    Feel free to review the source code for the Task class here.

    0 讨论(0)
提交回复
热议问题