【问题标题】:How to achieve "true" asynchrony如何实现“真正的”异步
【发布时间】:2015-01-30 13:36:36
【问题描述】:

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

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

真正的异步是不可能的,因为你有一个阻塞方法 你必须使用。所以,你所能做的就是一种解决方法——假的 异步,也就是阻塞线程池线程。

那么如何才能实现真正的异步,就像System.Threading.Tasks.Task 中的各种方法一样?如果您深入挖掘,难道不是所有“真正的异步”方法都只是阻塞了其他线程上的操作吗?

【问题讨论】:

  • @Yuval Itzchakov -- 你为什么要添加 c# 标签?
  • 所以这个问题会得到更广泛的关注。它与 C# 相关。

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


【解决方案1】:

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

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

虽然大多数真正的异步操作是 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)。您可以awaitTask 使用很长时间而不会阻塞任何线程。

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

【讨论】:

    【解决方案2】:

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

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

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

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

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

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2011-02-10
      • 2018-02-13
      • 2015-04-04
      • 1970-01-01
      • 1970-01-01
      • 2018-07-26
      • 1970-01-01
      • 2018-02-11
      相关资源
      最近更新 更多