简体   繁体   中英

Looking for guidance to understand how asynchronous Programming with Async and Await works

i go through a msdn sample code where a function is called when button is clicked and when routine is called then Await keyword is used and function has async keyword used.

private async void StartButton_Click(object sender, RoutedEventArgs e)
        {

            int contentLength = await AccessTheWebAsync();

            resultsTextBox.Text +=
                String.Format("\r\nLength of the downloaded string: {0}.\r\n", contentLength);
        }

async Task<int> AccessTheWebAsync()
        { 
            HttpClient client = new HttpClient();
            Task<string> getStringTask = client.GetStringAsync("http://msdn.microsoft.com");
            DoIndependentWork();
            string urlContents = await getStringTask;

            return urlContents.Length;
        }


        void DoIndependentWork()
        {
            resultsTextBox.Text += "Working . . . . . . .\r\n";
        }
  1. When AccessTheWebAsync is called then await keyword is used, what does it mean?
  2. When this function AccessTheWebAsync() will be executing then DoIndependentWork() function is called and i guess here control will be waiting until this function DoIndependentWork() is finished. Am I right?

again there is another statement called

string urlContents = await getStringTask;

why they use here await. if we do not use await here then what would happen?

Please guide me to understand the code that how it is working.

I have an intro blog post here , and the MSDN docs are also extremely good.

You can think of await as "pausing" the method ( without blocking the thread) until the awaitable operation completes. When this happens, it returns a task that is not completed to the calling method, so it also has the option to await .

Here's a brief description about async/await methods.

Async Methods:

  • Caller is not necessarily blocked for the full execution of async method
  • Possible return types
    • void : “fire-and-forget”
    • Task : allows to await termination of async method
    • Task<T> : allows to await termination and get result of type T
  • No ref or out parameter for async methods
  • Must again contain an await => Otherwise compile warning

await for Tasks

  • Await termination of a TPL task
  • Return result of task (if task with result type)
  • Must only occur in async methods => Otherwise compile error

An async method is partly synchronous and partly asynchronous

  • Caller synchronously executes the method until a blocking await
  • Thereafter, the method rest is asynchronously executed async & await Mechanism Efficient
public async Task<int> GetSiteLengthAsync(string url) 
{  
    HttpClient client = new HttpClient();               <= Sync  
    Task<string> download1 = client.GetStringAsync(url); <= Sync  
    string site1 = await download1;   <= Async (Another thread)
    return site1.Length;              <= Async (Another thread)
}

from MSDN:

the await operator is applied to a task in an asynchronous method to suspend the execution of the method until the awaited task completes. The task represents ongoing work.await does not block the thread on which it is executing. Instead, it causes the compiler to sign up the rest of the async method as a continuation on the awaited task. Control then returns to the caller of the async method. When the task completes, it invokes its continuation, and execution of the async method resumes where it left off.

So when the compiler encounter

     int contentLength = await AccessTheWebAsync();

it waits till the AccessTheWebAsync() task is complted

please take a look at this example C# Async,Await

Not sure if that simplier for you to understand that in the following way, but this is how it helped myself :

As you can see, the AccessTheWebAsync returns Task<int> but not just int .

If you would have called it without "await", you would just get the Task<int> object as its result. And could do anything further you want (manually) with that task: for instance, to wait until it finishes theTask.Wait(); and obtain the result of int in theTask.Result .

But await does all that instead of you and returns just int : Task<int> => int .

This is it.

All await does is blocks the thread until the result of an async operation returns.

Edit: sorry when I said block I should have said suspend, since blocking would prevent execution from continuing!

Edit2: As Alex pointed out - I should have probably said "execution is suspended" rather than the thread. Basically "Stuff happens until await returns but the point is it appears you are writing and executing synchronous code"

Since async operations have the potential to be take a while (eg web service calls), they tend to use callbacks to return a result.

If you have to handle callbacks in your code it can get a little messy, especially when waiting on multiple async tasks that are dependant on each other. Async/await and Task simplify the code so that you can write async code literally in the order you would read it.

eg example standard async code with callbacks:

public int CallSomeServiceAndReturnItsValue()   
{
    int result = 0;

    WebService.SomeAsyncServiceCall((svcResult) => { result = svcResult.Value; });

    return result;
}

and if you have multiple calls that need to be chained:

public int CallSomeServiceAndReturnItsValue()   
{
    int result = 0;

    WebService.GetSomeIdentifier((svcResult) => 
    {
         var identifier = svcResult.Value; 

         WebService.GetResult(identifier, (anotherResult) =>
            {
              result = anotherResult.Value;
            }
       }
    );

    return result;
}

As you can see, it starts getting messy, the code doesn't really read in an order that feels natural. The alternative is to use callback methods instead of anonymous methods but still, the callback methods are far away from the code that called them and things can feel disjointed

The other alternative is of course async/await which is much clearer

public int CallSomeServiceAndReturnItsValue()   
{
    int identifier = await WebService.GetSomeIdentifier();
    return await WebService.GetResult(identifier);
}

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM