gpt4 book ai didi

c# - 异步 CTP - 推荐的任务调度方法

转载 作者:可可西里 更新时间:2023-11-01 08:45:12 25 4
gpt4 key购买 nike

我目前正在开发一个在很大程度上使用 TAP 的异步应用程序。每个具有生成 Task 方法的类也有一个 TaskScheduler 注入(inject)其中。这使我们能够执行明确的任务调度,据我所知,这不是 Microsoft 使用异步 CTP 的方式。

我对新方法(隐式调度)的唯一问题是我们以前的理念一直是“我们知道延续将始终指定他们的任务调度程序,所以我们不需要担心我们完成的上下文任务”。

摆脱它确实让我们有点担心,因为它在避免细微的线程错误方面效果非常好,因为对于每一位代码,我们都可以看到编码器已经记得考虑他在哪个线程上。如果他们没有指定任务调度程序,那就是错误。

问题 1: 谁能向我保证隐式方法是个好主意?我看到 ConfigureAwait(false) 和遗留/第三方代码中的显式调度引入了很多问题。例如,我如何才能确保我的“充满等待”的代码始终在 UI 线程上运行?

问题 2: 那么,假设我们从代码中删除所有 TaskScheduler DI 并开始使用隐式调度,那么我们如何设置默认任务调度程序?如何在方法中途更改调度程序,就在等待一个昂贵的方法之前,然后再将其重新设置?

(附:我已经阅读了 http://msmvps.com/blogs/jon_skeet/archive/2010/11/02/configuring-waiting.aspx )

最佳答案

我会尝试回答。 ;)

Question 1: Can anyone reassure me that the implicit approach is a good idea? I see so many issues being introduced by ConfigureAwait(false) and explicit scheduling in legacy/third party code. How can I be sure my 'await-ridden' code is always running on the UI thread, for example?

ConfigureAwait(false) 的规则非常简单:如果您的方法的其余部分可以在线程池上运行,则使用它,如果您的方法的其余部分必须运行,则不要使用它在给定的上下文中(例如,UI 上下文)。

一般来说,ConfigureAwait(false) 应该被库代码使用,而不是被 UI 层代码(包括 UI 类型的层,例如 MVVM 中的 ViewModels)使用。如果该方法是部分后台计算和部分 UI 更新,则应将其拆分为两种方法。

Question 2: So, assuming we remove all TaskScheduler DI from our code and begin to use implicit scheduling, how do we then set the default task scheduler?

async/await 一般不使用TaskScheduler;他们使用“调度上下文”的概念。这实际上是 SynchronizationContext.Current,只有在没有 SynchronizationContext 时才会回退到 TaskScheduler.Current。因此,可以使用 SynchronizationContext.SetSynchronizationContext 替换您自己的调度程序。您可以在 this MSDN article on the subject 中阅读有关 SynchronizationContext 的更多信息.

默认的调度上下文应该是您几乎所有时间都需要的,这意味着您不需要去弄乱它。我只在进行单元测试或控制台程序/Win32 服务时更改它。

What about changing scheduler midway through a method, just before awaiting an expensive method, and then setting it back again afterward?

如果你想做一个昂贵的操作(大概是在线程池上),然后等待TaskEx.Run的结果。

如果您出于其他原因(例如,并发性)想要更改调度程序,则等待 TaskFactory.StartNew 的结果。

在这两种情况下,方法(或委托(delegate))都在另一个调度程序上运行,然后方法的其余部分在其常规上下文中恢复。

理想情况下,您希望每个 async 方法都存在于单个执行上下文中。如果方法的不同部分需要不同的上下文,则将它们拆分为不同的方法。此规则的唯一异常(exception)是 ConfigureAwait(false),它允许方法在任意上下文中启动,然后恢复到线程池上下文以执行剩余部分。 ConfigureAwait(false) 应该被视为一种优化(库代码默认启用),而不是一种设计理念。

以下是我在“Thread is Dead”演讲中的一些观点,我认为它们可能对您的设计有所帮助:

  • 遵循基于任务的异步模式指南。
  • 随着您的代码库变得更加异步,它在本质上将变得更加实用(与传统的面向对象相反)。这是正常的,应该接受。
  • 随着您的代码库变得更加异步,共享内存并发逐渐演变​​为消息传递并发(即 ConcurrentExclusiveSchedulerPair 是新的 ReaderWriterLock)。

关于c# - 异步 CTP - 推荐的任务调度方法,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/8760295/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com