异步等待CPU计算与IO操作的用法? [英] async await usages for CPU computing vs IO operation?

查看:183
本文介绍了异步等待CPU计算与IO操作的用法?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

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

I already know that async-await keeps the thread context , also handle exception forwarding etc.(which helps a lot).

但请考虑以下示例:

/*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*/   }

如果异步方法( httpClient.GetStringAsync )是一个IO操作(如上述示例所示)-我获得了这些东西:

If the async method (httpClient.GetStringAsync) is an IO operation ( like in my sample above) So - I gain these things :


  • 呼叫者线程未被阻止

  • > Worker 线程被阻止已发布,因为有一个 IO 操作(IO完成端口...)(GetStringAsync使用 TaskCompletionSource 而不打开新线程)

  • 保留的线程上下文

  • 抛出异常

  • Caller Thread is not blocked
  • Worker thread is released because there is an IO operation ( IO completion ports...) (GetStringAsync uses TaskCompletionSource and not open a new thread)
  • Preserved thread context
  • Exception is thrown back

但是如果不是 httpClient.GetStringAsync (IO操作),我有一个 Task CalcFirstMillionsDigitsOf_PI_Async (在一个单线程上进行大量的计算绑定操作)

But What if instead of httpClient.GetStringAsync (IO operation) , I have a Task of CalcFirstMillionsDigitsOf_PI_Async (heavy compute bound operation on a sperate thread)

似乎我在这里获得的唯一东西是:

It seems that the only things I gain here is :


  • 保留的线程上下文

  • 抛出异常

  • Caller 线程未被阻止

  • Preserved thread context
  • Exception is thrown back
  • Caller Thread is not blocked

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

But I still have another thread ( parallel thread) which executes the operation. and the cpu is switching between the main thread and the operation .

我的诊断是否正确?

推荐答案

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

Actually, you only get the second set of advantages in both cases. await doesn't start asynchronous execution of anything, it's simply a keyword to the compiler to generate code for handling completion, context etc.

您可以在'用await调用方法 ... ugh!',作者是Stephen Toub。

You can find a better explanation of this in '"Invoke the method with await"... ugh!' by Stephen Toub.

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

It's up to the asynchronous method itself to decide how it achieves the asynchronous execution:


  • 某些方法将使用Task来运行其代码在ThreadPool线程上,

  • 有些人将使用某些IO完成机制。甚至还有一个特殊的ThreadPool,您可以将其与Tasks 使用自定义TaskScheduler

  • 有些人会将TaskCompletionSource包装在事件或回调之类的另一种机制上。

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

In every case, it is the specific implementation that releases the thread (if one is used). The TaskScheduler releases the thread automatically when a Task finishes execution, so you get this functionality for cases #1 and #2 anyway.

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

What happens in case #3 for callbacks, depends on how the callback is made. Most of the time the callback is made on a thread managed by some external library. In this case you have to quickly process the callback and return to allow the library to reuse the method.

EDIT

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

Using a decompiler, it's possible to see that GetStringAsync uses the third option: It creates a TaskCompletionSource that gets signalled when the operation finishes. Executing the operation is delegated to an HttpMessageHandler.

这篇关于异步等待CPU计算与IO操作的用法?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆