如何实现"真正的"异步

ror*_*.ap 4 .net c# asynchronous task-parallel-library async-await

在他对这个问题的回答中,Stephen Cleary提到了"假"异步和"真实"异步.

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

真正的异步是不可能的,因为您必须使用阻塞方法.所以,你所能做的只是一个解决方法 - 伪异步,即阻塞线程池线程.

那怎么可能实现真正的异步,就像各种方法一样System.Threading.Tasks.Task?如果你挖得足够深入,是不是所有"真正的异步"方法只是阻止其他线程上的操作?

i3a*_*non 8

如果你挖得足够深入,是不是所有"真正的异步"方法只是阻止其他线程上的操作?

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

虽然大多数真正的异步操作都是I/O操作,但理解起来可能会过于复杂.(深刻阅读Stephen Cleary的"没有线索").

比方说,您想要await用户点击按钮.由于有一个Button.Click事件我们可以利用TaskCompletionSource异步等待事件被引发:

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

没有非泛型,TaskCompletionSource所以我使用bool一个虚拟值.这创建了一个Task未连接到线程的线程,它只是一个同步构造,只有在用户单击该按钮(直通SetResult)时才会完成.你可以awaitTask对不阻塞任何线程任何年龄.

Task.Delay对于这个问题实现非常相似,System.Threading.Timer在其回调中完成了等待的任务.


Yuv*_*kov 6

如果你挖得足够深入,是不是所有"真正的异步"方法只是阻止其他线程上的操作?

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

请参阅如何使用async/await在UI线程上异步运行多个任务?我详细介绍了重叠IO的工作方式.

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

A Task代表将在未来完成的工作单元.这与async IO无关.你可能认为这是因为async-await等待者很好地合作.大多数BCL库通过TaskAwaiter它来暴露异步IO操作,这就是为什么你认为它是实现异步的原因.