Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/csharp/270.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C# Task.Start、Task.RunSynchronously和同步上下文_C#_.net_Task Parallel Library_Task_Synchronizationcontext - Fatal编程技术网

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”。