我手动构造一个任务:
var task = new Task(() =>
Debug.WriteLine("Task"));
然后手动启动它:
task.Start(TaskScheduler.FromCurrentSynchronizationContext());
我希望可以通过预定SynchronizationContext.Post
。
但是如果以这种方式启动它:
task.RunSynchronously(TaskScheduler.FromCurrentSynchronizationContext());
它是通过SynchronizationContext.Send
还是直接通过调用任务的lambda来执行?
它是通过SynchronizationContext.Send执行还是直接通过调用任务的lambda执行?
这是怎么回事。首先,Task.RunSynchronously
尝试通过调用执行任务scheduler.TryExecuteTaskInline
。如果使用SynchronizationContextTaskScheduler
,则是这样的:
protected override bool TryExecuteTaskInline(Task task, bool taskWasPreviouslyQueued)
{
return ((SynchronizationContext.Current == this.m_synchronizationContext) && base.TryExecuteTask(task));
}
因此,如果在相同的同步上下文中,则任务lambda将直接在内部执行base.TryExecuteTask
。
否则,Task.RunSynchronously
将任务与任务计划程序放在队列中,并WaitHandle
通过阻止等待在任务上进行阻止。
SynchronizationContext.Send
并没有涉足任何情况。
有趣的是什么。AFAIK,在WPFDispatcherSynchronizationContext
中,主UI线程上可能有多个上下文,每个顶级窗口一个。因此,从理论上讲,RunSynchronously
可能会导致死锁。我将验证这一点。
更新后,WPF中的僵局是真实的。这是复制方法:
public partial class MainWindow : Window
{
public MainWindow()
{
InitializeComponent();
this.Loaded += MainWindow_Loaded;
}
void MainWindow_Loaded(object sMainWindow, RoutedEventArgs eMainWindow)
{
var task = new Task(() =>
Debug.WriteLine("Task"));
var scheduler = TaskScheduler.FromCurrentSynchronizationContext();
var window1 = new Window();
window1.Loaded += (sWindow1, eWindow1) =>
{
// Deadlock in WPF
task.RunSynchronously(scheduler);
Debug.WriteLine("Done!");
};
window1.Show();
}
}
本文收集自互联网,转载请注明来源。
如有侵权,请联系[email protected] 删除。
我来说两句