如何实现" true"异步

时间:2015-01-30 13:36:36

标签: c# .net asynchronous task-parallel-library async-await

在他对this question的回答中,Stephen Cleary指的是"假的"异步和"真"异步。

  

有一种更简单的方法来安排线程池的工作:Task.Run。

     

真正的异步是不可能的,因为你有一个阻止方法   你必须使用。所以,你所能做的只是一个解决方法 - 假的   asynchrony,a.k.a。阻塞线程池线程。

如何实现真正的异步,就像System.Threading.Tasks.Task中的各种方法一样? Aren" all"真正异步"如果你挖得足够深,那么方法只是阻塞其他线程上的操作?

2 个答案:

答案 0 :(得分:8)

  

Aren" all"真正异步"如果你挖得足够深,那么方法只是阻塞其他线程上的操作?

没有。真正的异步操作在整个操作过程中不需要线程,并且使用一个限制可伸缩性并且会损害性能。

虽然大多数真正的异步操作都是I / O操作,但理解起来可能会过于复杂。 (深刻阅读Stephen Cleary的There Is No Thread)。

例如,假设您要await用户点击按钮。由于存在Button.Click事件,我们可以利用TaskCompletionSource异步等待事件被提升:

var tcs = new TaskCompletionSource<bool>();
_button.Click += (sender, EventArgs e) => tcs.SetResult(false);
await tcs.Task;

没有非通用TaskCompletionSource因此我使用具有虚拟值的bool。这会创建一个Task,它不会连接到某个帖子,它只是一个同步构造,只有在用户点击该按钮时才能完成(通过SetResult)。你可以await Task多年,而不会阻止任何线程。

Task.DelaySystem.Threading.Timer非常相似地实现,在其回调中完成等待的任务。

答案 1 :(得分:6)

  

如果你深入挖掘,是不是所有“真正异步”的方法都只是阻塞其他线程上的操作?

恰恰相反。真正的异步方法一直是异步到操作系统级别。默认情况下,这些类型的方法即使在设备驱动程序级别也不会阻塞,使用IRP(IO请求数据包)和DPC。

请参阅How does running several tasks asynchronously on UI thread using async/await work?我详细介绍了重叠IO的工作方式。

  

如何实现真正的异步,就像System.Threading.Tasks.Task中的各种方法一样?

Task表示将在未来中完成的工作单元。这与async IO无关。您可能假设的原因是因为async-await awaitables 很好地协同工作。大多数BCL库通过TaskAwaiter公开异步IO操作,这就是为什么你认为它是实现异步的原因。