Roy*_*mir 20 .net c# task-parallel-library async-await
我已经 从Noseratio那里读到了这个问题,这个问题显示了一个在等待完成其操作之后TaskScheduler.Current不一样的行为.
答案指出:
如果没有执行任何实际任务,则与之
TaskScheduler.Current相同TaskScheduler.Default
这是真的.我已在这里看到它 :
TaskScheduler.Default
- 返回一个实例
ThreadPoolTaskSchedulerTaskScheduler.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();
}
Run Code Online (Sandbox Code Playgroud)
第一个Messagebox是"True",第二个是"False"
题:
如您所见,我确实创建了一个实际任务.
我可以理解为什么第一个MessageBox产量True.多数民众赞成:
如果从执行任务中调用,则返回当前正在执行的任务的TaskScheduler
而那个任务确实有ts发送的内容TaskScheduler.FromCurrentSynchronizationContext()
但为什么在第二个 MessageBox中没有保留 上下文?对我来说,斯蒂芬的回答并不清楚.
附加信息 :
如果我写(第二个消息框):
MessageBox.Show((TaskScheduler.Current == TaskScheduler.Default).ToString());
Run Code Online (Sandbox Code Playgroud)
它确实屈服了true.但为什么 ?
i3a*_*non 10
混淆的原因是:
TaskScheduler.在UI线程上运行的代码的默认情况是TaskScheduler.Current存储ThreadPoolTaskScheduler和SynchronizationContext.Current存储WindowsFormsSynchronizationContext(或其他UI应用程序中的相关代码)ThreadPoolTaskSchedulerin TaskScheduler.Current并不一定意味着它TaskScheduler被用来运行当前的代码.这也意味着TaskSchdeuler.Current == TaskScheduler.Default,因此"没有TaskScheduler用的存在".TaskScheduler.FromCurrentSynchronizationContext()没有返回"acutal" TaskScheduler.它返回一个"代理",将任务直接发布到捕获的SynchronizationContext.因此,如果您在开始任务之前(或在任何其他地方)运行测试,您将获得与等待之后相同的结果:
MessageBox.Show(TaskScheduler.Current == TaskScheduler.FromCurrentSynchronizationContext()); // False
Run Code Online (Sandbox Code Playgroud)
因为TaskScheduler.Current是ThreadPoolTaskScheduler和TaskScheduler.FromCurrentSynchronizationContext()返回一个SynchronizationContextTaskScheduler.
这是你的例子的流程:
SynchronizationContextTaskScheduler从UI SynchronizationContext(即WindowsFormsSynchronizationContext)创建一个新的.Task.Factory.StartNew上TaskScheduler.由于它只是一个"代理",它将委托发布到WindowsFormsSynchronizationContext在UI线程上调用它的代理.SynchronizationContextTaskScheduler.WindowsFormsSynchronizationContext.WindowsFormsSynchronizationContext而不是SynchronizationContextTaskScheduler因为SynchronizationContexts具有优先权(这可以在其中看到Task.SetContinuationForAwait).然后,它定期运行在UI线程上,没有任何"特殊" TaskScheduler等等TaskScheduler.Current == TaskScheduler.Default.因此,创建的任务在代理TaskScheduler上运行,该代理SynchronizationContext在await发布到该代理之后使用但是继续,SynchronizationContext而不是TaskScheduler.
| 归档时间: |
|
| 查看次数: |
745 次 |
| 最近记录: |