使用异步和等待回调

时间:2016-09-02 06:53:33

标签: c# asynchronous async-await c#-6.0

我对异步作业的执行顺序有疑问。

我会用例子问我的问题,因为它更易于理解。

这是https://msdn.microsoft.com/en-us/library/mt674882.aspx的一个官方例子,但有一些转折。

async Task<int> AccessTheWebAsync()
{ 
    HttpClient client = new HttpClient();

    //async operation:
    Task<string> getStringTask = client.GetStringAsync("http://msdn.microsoft.com");

    // You can do work here that doesn't rely on the string from GetStringAsync.
    DoWork1();

    // The await operator suspends AccessTheWebAsync.
    string urlContents = await getStringTask;

    DoWork2();

    return urlContents.Length;
}

我可以说DoWork2client.GetStringAsync的回调吗?

如果是这样,DoWork2完成client.GetStringAsync之后DoWork1不会立即执行client.GetStringAsync如果{{1}}的运行时间超过{{1}}。

我在这儿吗?

3 个答案:

答案 0 :(得分:5)

  完成后,

You have an error in your SQL syntax; check the manual that corresponds to your MySQL server version for the right syntax to use near 'LEFT JOIN usertable ut ON ut.id = user GROUP BY user' 不会立即执行   如果DoWork2的运行时间比client.GetStringAsync长,则为DoWork1   client.GetStringAsync

一旦点击await client.GetStrinkAsyncDoWork1()已经完成,从您的示例中看,它的执行是同步的。 client.GetStringAsync完成后,DoWork2将设置为执行。

执行流程为:

  1. GetStringAsync异步启动。它会一直执行,直到它达到它的第一个内部await,然后将控制权交还给AccessTheWebAsync
  2. DoWork1()开始了。因为它是同步的,所以每个人都在等待它的完成
  3. client.GetStringAsync 异步等待完成。 await自然会对其调用者产生执行控制权。
  4. client.GetStringAsync完成后,执行将返回AccessTheWebAsyncDoWork2()将同步执行。
  5. urlContents.length将被退回。
  6. 通常,第一个await关键字之后的所有内容都设置为该方法其余部分的延续。

答案 1 :(得分:4)

Yuval's answer是正确的。

回答你的后续问题:

  

有没有办法让client.GetStringAsync完成后立即执行DoWork2?

可能。这取决于此代码的上下文。它不可能同时在UI线程上运行DoWork1DoWork2(显然,单个线程一次只能执行一项操作)。但是如果从线程池上下文中调用它,那么可以同时运行它们。

但是,你应该将你的想法转移到&#34;回调&#34;到&#34;操作&#34;。也就是说,不要将其视为DoWork2是一个&#34;回调&#34; GetStringAsync。相反,想一想:我有一个操作GetStringAsync,我有一个操作DoWork2;我需要一个新的操作来做一个然后另一个。

一旦你按照这种方式改变思路,解决方案就是为新操作编写一个方法:

async Task<string> GetStringAndDoWork2Async()
{
  HttpClient client = new HttpClient();
  var result = await client.GetStringAsync("http://msdn.microsoft.com");
  DoWork2();
  return result;
}

现在,您可以在更高级别的方法中使用该新操作:

async Task<int> AccessTheWebAsync()
{
  var task = GetStringAndDoWork2Async();

  DoWork1();

  string urlContents = await task;

  return urlContents.Length;
}

答案 2 :(得分:-1)

在:

//async operation:
Task<string> getStringTask = client.GetStringAsync("http://msdn.microsoft.com");

你正在创建一个运行异步操作的Task,并立即返回给调用者,下一个DoWork1()同步执行,一旦完成,string urlContents = await getStringTask;暂停方法的继续,直到等待的任务完成;完成后,程序继续DoWork2()