Roy*_*mir 20 .net c# task-parallel-library async-await
我已经 从Noseratio那里读到了这个问题,这个问题显示了一个在等待完成其操作之后TaskScheduler.Current
不一样的行为.
答案指出:
如果没有执行任何实际任务,则与之
TaskScheduler.Current
相同TaskScheduler.Default
这是真的.我已在这里看到它 :
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();
}
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应用程序中的相关代码)ThreadPoolTaskScheduler
in 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
因为SynchronizationContext
s具有优先权(这可以在其中看到Task.SetContinuationForAwait
).然后,它定期运行在UI线程上,没有任何"特殊" TaskScheduler
等等TaskScheduler.Current == TaskScheduler.Default
.因此,创建的任务在代理TaskScheduler
上运行,该代理SynchronizationContext
在await发布到该代理之后使用但是继续,SynchronizationContext
而不是TaskScheduler
.
归档时间: |
|
查看次数: |
745 次 |
最近记录: |