我已阅读Noseratio中的this question,其中显示了在等待完成其操作后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();
}
First Messagebox为“True”,第二个为“False”
问题:
正如您所看到的,我确实创建了一个实际的任务。
我可以理解为什么第一个MessageBox会产生True
。多数民众赞成:
如果从执行任务中调用将返回TaskScheduler 当前正在执行的任务
该任务的确有ts
,即TaskScheduler.FromCurrentSynchronizationContext()
但为什么上下文 对我来说,斯蒂芬的回答并不清楚。
其他信息:
如果我改写(第二个消息框):
MessageBox.Show((TaskScheduler.Current == TaskScheduler.Default).ToString());
确实会产生true
。但为什么 ?
答案 0 :(得分:10)
混淆的原因是:
TaskScheduler
。在UI线程上运行的代码的默认情况是TaskScheduler.Current
存储ThreadPoolTaskScheduler
和SynchronizationContext.Current
存储WindowsFormsSynchronizationContext
(或其他UI应用程序中的相关存储)ThreadPoolTaskScheduler
中的TaskScheduler.Current
并不一定意味着它是用于运行当前代码的TaskScheduler
。它还意味着TaskSchdeuler.Current == TaskScheduler.Default
,因此“没有使用TaskScheduler
”。 TaskScheduler.FromCurrentSynchronizationContext()
未返回“acutal”TaskScheduler
。它返回一个“代理”,可以将任务直接发布到捕获的SynchronizationContext
。因此,如果您在开始任务之前(或在任何其他地方)运行测试,您将获得与等待之后相同的结果:
MessageBox.Show(TaskScheduler.Current == TaskScheduler.FromCurrentSynchronizationContext()); // False
由于TaskScheduler.Current
为ThreadPoolTaskScheduler
且TaskScheduler.FromCurrentSynchronizationContext()
返回SynchronizationContextTaskScheduler
。
这是你的例子的流程:
SynchronizationContextTaskScheduler
(即SynchronizationContext
)创建新的WindowsFormsSynchronizationContext
。Task.Factory.StartNew
上的TaskScheduler
计划您创建的任务。由于它只是一个“代理”,它将委托发布到WindowsFormsSynchronizationContext
,并在UI线程上调用它。SynchronizationContextTaskScheduler
相关联。WindowsFormsSynchronizationContext
时被“暂停”。WindowsFormsSynchronizationContext
而不是SynchronizationContextTaskScheduler
,因为SynchronizationContext
具有优先权(this can be seen in Task.SetContinuationForAwait
)。然后在UI线程上定期运行,没有任何“特殊”TaskScheduler
所以TaskScheduler.Current == TaskScheduler.Default
。因此,创建的任务在代理TaskScheduler
上运行,代理SynchronizationContext
使用SynchronizationContext
,但await后的延续发布到TaskScheduler
而不是{{1}}。< / p>