它會通過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));
}
所以,如果在同一同步上下文,任務拉姆達會直接內base.TryExecuteTask
執行。
否則,Task.RunSynchronously
將任務與任務調度程序排隊,並使用阻塞等待阻塞任務的WaitHandle
。
SynchronizationContext.Send
確實不是涉及任何情況。
有趣的是這個。 AFAIK,在WPF中,主UI線程上可能會有多個DispatcherSynchronizationContext
上下文,每個頂級窗口上有一個上下文。因此,理論上,RunSynchronously
可能導致死鎖。我要驗證這一點。
更新,WPF中的死鎖是real。這裏是如何重載:
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();
}
}
我很難想象死鎖,在這裏。你介意描述這如何導致僵局?即誰在爭奪什麼資源? – Thomas
@Thomas,沒有比賽,但任務完成回調通過SynchrnizationContext.Post發佈,然後線程阻塞task.RunSynchronously內同一任務的句柄,導致死鎖。我正在通過手機進行此操作,不能進入更多細節,但是您可以搜索Stephen Clearly的「不要阻止異步代碼」。 – Noseratio