它会通过 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,在 WPF 中,主 UI 线程上可能有多个DispatcherSynchronizationContext
上下文,每个顶级窗口一个。因此,理论上,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();
}
}