使用异步和等待回调

der*_*rek 2 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;
}
Run Code Online (Sandbox Code Playgroud)

我可以说DoWork2是回调client.GetStringAsync吗?

如果是这样,DoWork2则在client.GetStringAsyncIF DoWork1运行完成后不会立即执行client.GetStringAsync.

我在这儿吗?

Yuv*_*kov 5

DoWork2client.GetStringAsync如果DoWork1运行时间超过 ,则不会立即执行 client.GetStringAsync

一旦你达到这一点await client.GetStrinkAsync,DoWork1()已经完成,从你的例子看,它的执行是同步的.一旦client.GetStringAsync完成,则DoWork2设置为执行.

执行流程将是:

  1. GetStringAsync异步启动.它会被执行,直到它击中它的第一个内部await,然后将控制权返回到AccessTheWebAsync.
  2. DoWork1()揭开序幕.因为它是同步的,所以每个人都在等待它的完成
  3. client.GetStringAsync异步等待完成.await自然会对其来电者产生执行控制权.
  4. 一旦client.GetStringAsync完成,执行将返回AccessTheWebAsyncDoWork2()将同步执行.
  5. urlContents.length 将被退回.

通常,第一个await关键字后面的所有内容都设置为该方法其余部分的延续.


Ste*_*ary 5

尤瓦尔的回答是正确的。

要回答您的后续问题:

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

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

但是,您应该将您的想法从“回调”转移到“操作”。也就是说,不要把它看作DoWork2是一个的“回调” GetStringAsync。相反,可以这样想:我有一个手术GetStringAsync,我有一个手术DoWork2;我需要一个新的操作来执行一个然后另一个。

一旦您以这种方式转变思维,解决方案就是为新操作编写一个方法:

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

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

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

  DoWork1();

  string urlContents = await task;

  return urlContents.Length;
}
Run Code Online (Sandbox Code Playgroud)