调用异步方法时会发生什么?

时间:2015-04-22 07:30:31

标签: c# .net async-await

我试着理解为什么更好地使用' Async'方法比使用简单的旧同步方式。

我不明白有一个小问题。

以同步方式:

  1. 我有一些调用方法FileStream.Read(...)的线程。
  2. 因为调用此方法是同步的,所以调用线程将等待,直到IRP(I / O请求包)将发出此Io请求完成的信号。 直到IRP将返回==>这个线程将暂停(睡眠)。
  3. 以A同步的方式:

    1. 我有一些线程(任务..让我们调用这个线程' TheadAsync01')调用方法FileStream.ReadAsync(...)
    2. 因为调用此方法是A-Synchronous,所以调用线程不会等到IRP(I / O请求包)发出此IO请求完成的信号;这个调用线程将继续他的下一步行动。
    3. 现在,当IRP发出信号表示此IO请求已完成时发生了什么?

      (主题TheadAsync01现在正在做其他事情,并且无法继续使用' FileStream.ReadAsync'现在返回。

      其他线程会继续使用ReadAsync的返回值继续下一个操作吗?

      我在这里不明白?

3 个答案:

答案 0 :(得分:5)

困扰你的原因是这个错误的假设:

  

线程TheadAsync01现在正在做其他事情并且无法继续   使用' FileStream.ReadAsync'现在回来。

在典型的应用程序中,I / O是迄今为止最耗时的任务。

正确使用TPL时,线程不会被耗时的操作阻塞。相反,所有耗时的工作(换句话说,任何I / O)都是通过await委派的。因此,当您的IRP发出信号时,线程将无法工作,或者很快就会免费。

如果有一些繁重的计算(非常耗时的 I / O),您需要相应地进行规划,例如在专用线程上运行它。

答案 1 :(得分:2)

函数ReadAsync立即返回一个值,即一个Task对象。在某个地方你应该用返回值做一些事情。规范的方法是使用await:

await FileStream.ReadAsync(...)

这将确保在ReadAsync完成其工作之前,调用站点不会继续操作。如果你想在此期间做某事,你可以稍后等待任务对象,或者你可以手动处理任务对象。

如果您只是调用ReadAsync,忽略返回的任务对象,不执行任何操作,那么您的阅读大多是昂贵的无操作。

答案 2 :(得分:1)

当*** Async方法返回任务或任务时,您可以使用它来跟踪异步操作的运行。通过在任务上调用.Wait(),可以使调用与调用代码同步。或者,从.Net 4.5开始,您可以等待任务。

e.g:

private async void DoFileRead(...)
{
    var result = await fileStream.ReadAsync(...);
    // Do follow on tasks
}

在这种情况下,任何后续代码都将被编译器包含在一个延续中,并在异步调用完成时执行。使用async关键字的一个要求是使用async关键字标记调用方法(参见上面的示例)。