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

查看:24
本文介绍了异步等待 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*/   }

如果 async 方法 (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 操作),我有一个 CalcFirstMillionsDigitsOf_PI_AsyncTask(在单独的线程)

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 :

  • 保留的线程上下文
  • 抛出异常
  • 调用者线程未被阻塞
  • 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 .

我的诊断是否正确?

推荐答案

实际上,在这两种情况下,您只会获得第二组优势.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 调用方法"...呃!' by 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 完成机制.甚至还有一个特殊的线程池,您可以将其与任务一起使用 使用自定义 TaskScheduler
  • 有些人会将 TaskCompletionSource 包装在另一种机制上,例如事件或回调.

在每种情况下,释放线程的都是特定的实现(如果使用了的话).当 Task 完成执行时,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.

编辑

使用反编译器,可以看到 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天全站免登陆