avo*_*avo 8 .net c# task synchronizationcontext task-parallel-library
我手动构建一个任务:
var task = new Task(() =>
Debug.WriteLine("Task"));
Run Code Online (Sandbox Code Playgroud)
然后手动启动它:
task.Start(TaskScheduler.FromCurrentSynchronizationContext());
Run Code Online (Sandbox Code Playgroud)
我希望它能通过预定SynchronizationContext.Post.
但如果以这种方式启动它:
task.RunSynchronously(TaskScheduler.FromCurrentSynchronizationContext());
Run Code Online (Sandbox Code Playgroud)
是通过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));
}
Run Code Online (Sandbox Code Playgroud)
因此,如果在同一个同步上下文中,任务lambda将直接在内部执行base.TryExecuteTask.
否则,Task.RunSynchronously使用任务调度程序对任务进行排队,并WaitHandle使用阻塞等待阻止任务.
SynchronizationContext.Send并没有涉足任何情况.
有趣的是这个.AFAIK,在WPF DispatcherSynchronizationContext中,主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();
}
}
Run Code Online (Sandbox Code Playgroud)
| 归档时间: |
|
| 查看次数: |
4910 次 |
| 最近记录: |