【发布时间】:2015-11-20 14:56:20
【问题描述】:
我从 Noseratio 读到了 this question,它显示了在 awaitable 完成操作后 TaskScheduler.Current 不一样的行为。
答案表明:
如果没有正在执行的实际任务,那么
TaskScheduler.Current与TaskScheduler.Default相同
这是真的。我已经看过了here:
TaskScheduler.Default
- 返回
ThreadPoolTaskScheduler的一个实例TaskScheduler.Current
- 如果从正在执行的任务中调用,将返回
TaskScheduler当前正在执行的任务- 如果从任何其他地方调用将返回
TaskScheduler.Default
但后来我想,如果是这样,让我们做创建一个实际的Task(而不仅仅是Task.Yield())并对其进行测试:
async void button1_Click_1(object sender, EventArgs e)
{
var ts = TaskScheduler.FromCurrentSynchronizationContext();
await Task.Factory.StartNew(async () =>
{
MessageBox.Show((TaskScheduler.Current == ts).ToString()); //True
await new WebClient().DownloadStringTaskAsync("http://www.google.com");
MessageBox.Show((TaskScheduler.Current == ts).ToString());//False
}, CancellationToken.None, TaskCreationOptions.None,ts).Unwrap();
}
第一个消息框是“真”,第二个是“假”
问题:
如你所见,我确实创建了一个实际任务。
我可以理解为什么第一个 MessageBox 产生 True。那是因为:
如果从正在执行的任务中调用,将返回 TaskScheduler 当前正在执行的任务
该任务确实有ts,即发送的TaskScheduler.FromCurrentSynchronizationContext()
但是 为什么 上下文是 not 保留在 second MessageBox ?对我来说,斯蒂芬的回答并不清楚。
附加信息:
如果我写的是(第二个消息框):
MessageBox.Show((TaskScheduler.Current == TaskScheduler.Default).ToString());
它确实产生了 true 。但为什么 ?
【问题讨论】:
-
很好的问题,但如果
task scheduler != synchronization context? -
硬性规则的一个很好的例子:永远不要假设
TaskScheduler.Current是你认为的那样 :) 对于任务操作 lambda 的范围,它只能保证是你传递给Factory.StartNew的内容(在您的情况下是Func<Task>,并在遇到第一个await时返回)。任何其他行为都应视为实现细节。
标签: c# .net async-await task-parallel-library