TaskEx.Yield(的TaskScheduler)

Law*_*eld 3 .net c# task-parallel-library async-ctp .net-4.5

上个月我问了以下问题,这导致我学到了TaskEx.Yield:

异步方法在第一次"等待"之前是否有昂贵的代码?

但是,我已经意识到这个方法实际上将所有后续代码提交给环境TaskScheduler.在真正的DI精神中,我们的团队同意尽可能避免使用环境实例,所以我想知道是否可以明确指定TaskScheduler使用?

像下面这样的东西会很棒:

public static YieldAwaitable Yield(TaskScheduler taskScheduler)
{
    return new YieldAwaitable(taskScheduler);
}
Run Code Online (Sandbox Code Playgroud)

但是,Async CTP的当前实现仅提供:

public static YieldAwaitable Yield()
{
    return new YieldAwaitable(SynchronizationContext.Current ?? TaskScheduler.Current);
}
Run Code Online (Sandbox Code Playgroud)

以下是否会提供可接受的有效替代方案?

await Task.Factory.StartNew(() => { }, CancellationToken.None, TaskCreationOptions.None, this.TaskScheduler);
Run Code Online (Sandbox Code Playgroud)

Ste*_*ary 5

在真正的DI精神中,我们的团队同意尽可能避免使用环境实例......

异步语言支持基于隐式调度上下文.我不认为这里需要依赖注入.调用async方法的任何方法都可以在必要时提供自己的上下文.

你的选择:

await Task.Factory.StartNew(() => { }, CancellationToken.None, TaskCreationOptions.None, this.TaskScheduler);
Run Code Online (Sandbox Code Playgroud)

不会按预期工作.这会将noop lambda排队到特定的lambi TaskScheduler,然后在隐式调度上下文中恢复该方法.

早期版本的Async CTP确实提供了"屈服于另一个上下文"的方法,称为SwitchTo.它被删除了,因为它太容易被误用了.

就个人而言,我认为async使用其调用方法提供的隐式调度上下文来保持代码更为清晰.

PS创建和安装自己的上下文(例如,用于测试目的)并非(太)困难.我写AsyncContext了一个简单的调度上下文,用于单元测试和控制台程序.在异步CTP自带GeneralThreadAffineContext,WindowsFormsContext以及WpfContext进行测试.其中任何一个都可以使用安装SynchronizationContext.SetSynchronizationContext.IMO,DI太过分了.