异步等待CPU计算与IO操作的用法?

罗伊·纳米尔(Roi Namir)

我已经知道可以async-await保留线程上下文,还可以处理异常转发等(这很有帮助)。

但是,请考虑以下示例:

/*1*/   public async Task<int> ExampleMethodAsync()
/*2*/   {
/*3*/       var httpClient = new HttpClient(); 
/*4*/      
/*5*/       //start async task...
/*6*/       Task<string> contentsTask = httpClient.GetStringAsync("http://msdn.microsoft.com");
/*7*/   
/*8*/       //wait and return...  
/*9*/       string contents = await contentsTask;
/*10*/   
/*11*/       //get the length...
/*12*/       int exampleInt = contents.Length;
/*13*/       
/*14*/       //return the length... 
/*15*/       return exampleInt;
/*16*/   }

如果async方法(httpClient.GetStringAsync)是IO操作(如上面的示例中所示),那么-我得到了这些东西:

  • 呼叫者线程未被阻止
  • 由于存在 IO 操作(IO完成端口...), 因此释放了工作线程 (GetStringAsync使用TaskCompletionSource而不打开新线程)
  • 保留线程上下文
  • 异常被抛出

但是如果不是httpClient.GetStringAsync(IO操作)而不是独立线程上的大量计算绑定操作)的任务CalcFirstMillionsDigitsOf_PI_Async该怎么办?

看来我在这里获得的唯一收获是:

  • 保留线程上下文
  • 异常被抛出
  • 呼叫者线程未被阻止

但是我还有另一个线程(并行线程)来执行操作。并且cpu在主线程和操作之间切换。

我的诊断是否正确?

帕纳吉奥提斯·卡纳沃斯(Panagiotis Kanavos)

实际上,在两种情况下,您都只能获得第二套优势。await不会启动任何东西的异步执行,它只是编译器的一个关键字,用于生成用于处理完成,上下文等的代码。

您可以在“ “使用等待调用方法”中找到对此的更好解释斯蒂芬·图布(Stephen Toub)

由异步方法本身决定如何实现异步执行:

  • 某些方法将使用Task在ThreadPool线程上运行其代码,
  • 有些将使用某些IO完成机制。甚至还有一个特殊的ThreadPool,您可以将其与带有自定义TaskScheduler的Tasks一起使用
  • 有些人会将TaskCompletionSource包装在事件或回调之类的另一种机制上。

在每种情况下,都是释放线程(如果使用了线程)的特定实现。TaskScheduler在Task完成执行时自动释放线程,因此无论如何情况1和2都会获得此功能。

在回调的情况3下会发生什么,取决于如何进行回调。大多数情况下,回调是在某个外部库管理的线程上进行的。在这种情况下,您必须快速处理回调并返回以允许库重用该方法。

编辑

使用反编译器,可能会看到它GetStringAsync使用了第三个选项:它创建一个TaskCompletionSource,当操作完成时会发出信号。执行该操作委托给HttpMessageHandler。

本文收集自互联网,转载请注明来源。

如有侵权,请联系[email protected] 删除。

编辑于
0

我来说两句

0条评论
登录后参与评论

相关文章

来自分类Dev

立即等待异步操作

来自分类Dev

开始异步操作,然后等待

来自分类Dev

开始异步操作,然后等待

来自分类Dev

反应:shouldComponentUpdate等待异步操作

来自分类Dev

IO异步方法中TaskCompletionSource的用法

来自分类Dev

异步CPU读取和GPU + CPU计算

来自分类Dev

在RxJS Observable的onNext中等待异步操作

来自分类Dev

等待异步操作在Swift中完成

来自分类Dev

asio-等待异步操作完成

来自分类Dev

如何使Lambda函数等待异步操作完成?

来自分类Dev

是否可以等待未声明为异步的IO操作?如果没有,我该怎么办?

来自分类Dev

自定义线程的等待/异步的用法(和优点)

来自分类Dev

如何诊断 Ubuntu CPU 峰值/IO 等待?

来自分类Dev

OkHttp和Retrofit用于异步操作中ThreadPoolExecutor用法的差异

来自分类Dev

等待功能,直到在python异步IO中收到回调

来自分类Dev

'收藏被修改;枚举操作可能无法使用异步/等待执行

来自分类Dev

不处理异步操作时应在哪里等待?

来自分类Dev

NSOperationQueue如何等待两个异步操作?

来自分类Dev

使用Task.WhenAny等待几种不同的异步操作的结果

来自分类Dev

具有异步/等待的可扩展操作

来自分类Dev

Ember.js验收测试不等待异步数据操作

来自分类Dev

Python异步:在执行其他操作时等待标准输入

来自分类Dev

如何在更改网址之前等待成功的异步操作?

来自分类Dev

如何在循环的每次迭代中等待异步操作完成

来自分类Dev

Nuxt-异步操作后等待(this。$ store.dispatch)

来自分类Dev

用异步操作等待字典的正确方法是什么?

来自分类Dev

Boost awaitable:如何在帖子内部等待异步操作

来自分类Dev

异步等待MVC操作返回Task而不是ActionResult

来自分类Dev

Task.Result等待而不是继续异步操作

Related 相关文章

  1. 1

    立即等待异步操作

  2. 2

    开始异步操作,然后等待

  3. 3

    开始异步操作,然后等待

  4. 4

    反应:shouldComponentUpdate等待异步操作

  5. 5

    IO异步方法中TaskCompletionSource的用法

  6. 6

    异步CPU读取和GPU + CPU计算

  7. 7

    在RxJS Observable的onNext中等待异步操作

  8. 8

    等待异步操作在Swift中完成

  9. 9

    asio-等待异步操作完成

  10. 10

    如何使Lambda函数等待异步操作完成?

  11. 11

    是否可以等待未声明为异步的IO操作?如果没有,我该怎么办?

  12. 12

    自定义线程的等待/异步的用法(和优点)

  13. 13

    如何诊断 Ubuntu CPU 峰值/IO 等待?

  14. 14

    OkHttp和Retrofit用于异步操作中ThreadPoolExecutor用法的差异

  15. 15

    等待功能,直到在python异步IO中收到回调

  16. 16

    '收藏被修改;枚举操作可能无法使用异步/等待执行

  17. 17

    不处理异步操作时应在哪里等待?

  18. 18

    NSOperationQueue如何等待两个异步操作?

  19. 19

    使用Task.WhenAny等待几种不同的异步操作的结果

  20. 20

    具有异步/等待的可扩展操作

  21. 21

    Ember.js验收测试不等待异步数据操作

  22. 22

    Python异步:在执行其他操作时等待标准输入

  23. 23

    如何在更改网址之前等待成功的异步操作?

  24. 24

    如何在循环的每次迭代中等待异步操作完成

  25. 25

    Nuxt-异步操作后等待(this。$ store.dispatch)

  26. 26

    用异步操作等待字典的正确方法是什么?

  27. 27

    Boost awaitable:如何在帖子内部等待异步操作

  28. 28

    异步等待MVC操作返回Task而不是ActionResult

  29. 29

    Task.Result等待而不是继续异步操作

热门标签

归档