C# Task.Start、Task.RunSynchronously和同步上下文
我手动构造任务:C# Task.Start、Task.RunSynchronously和同步上下文,c#,.net,task-parallel-library,task,synchronizationcontext,C#,.net,Task Parallel Library,Task,Synchronizationcontext,我手动构造任务: var task = new Task(() => Debug.WriteLine("Task")); task.Start(TaskScheduler.FromCurrentSynchronizationContext()); 然后手动启动: var task = new Task(() => Debug.WriteLine("Task")); task.Start(TaskScheduler.FromCurrentSynchroniza
var task = new Task(() =>
Debug.WriteLine("Task"));
task.Start(TaskScheduler.FromCurrentSynchronizationContext());
然后手动启动:
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
在任何情况下都不会参与
这有什么意思。另外,在WPF中,主UI线程上可能有多个DispatcherSynchronizationContext
上下文,每个顶级窗口一个。因此,理论上,同步运行
可能会导致死锁。我要核实一下
已更新,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();
}
}
我很难想象这里的僵局。您介意描述一下这是如何导致死锁的吗?i、 e.谁在争夺什么资源?@Thomas,没有竞速,但是任务完成回调是通过SynchrnizationContext.Post发布的,然后线程在task.RunSynchronously内阻塞同一任务的句柄,导致死锁。我是在电话里说这句话的,我不能说更多的细节,但你可以搜索Stephen Clear的“don't block on asynchronous code”。