C# 使用同步上下文在同一UI线程中完成操作

C# 使用同步上下文在同一UI线程中完成操作,c#,multithreading,synchronization,task-parallel-library,C#,Multithreading,Synchronization,Task Parallel Library,我想从UI线程1创建一个进度UIthread2。 进度UI在thread3中创建任务并等待其完成 taskthread3完成并调用必须在thread2中执行的进程UI的关闭 对于关闭操作,我使用AsyncOperationManager捕获thread2的上下文,然后从thread4执行POST方法 但是关闭总是从另一个线程发生 下面的所有代码都来自ProgressWindows类 _currentTask = new Progress<double>(Close); // I ca

我想从UI线程1创建一个进度UIthread2。 进度UI在thread3中创建任务并等待其完成

taskthread3完成并调用必须在thread2中执行的进程UI的关闭

对于关闭操作,我使用AsyncOperationManager捕获thread2的上下文,然后从thread4执行POST方法

但是关闭总是从另一个线程发生

下面的所有代码都来自ProgressWindows类

_currentTask = new Progress<double>(Close); // I call this in progress UI constructor.

// This is invoked in constructor of Progress class which is used inside ProgressWindow.
_asyncOperation = AsyncOperationManager.CreateOperation(null);

public static void Run2(Action action) 
{ 
    Debug.WriteLine(":: Run2 in thread: {0}", Thread.CurrentThread.ManagedThreadId); 

    var th = new Thread(_ => 
    { 
        Debug.WriteLine(":: StartNew in thread: {0}", Thread.CurrentThread.ManagedThreadId); 
        var progress = new ProgressWindow(); 
        progress.Run(action); 
    }); 

    th.SetApartmentState(ApartmentState.STA); 
    th.Start(); 
} 


 public void Run(Action action) 
 { 
    Debug.WriteLine(":: Run in thread: {0}", Thread.CurrentThread.ManagedThreadId); 

    SetupProgressBar(); 
    RunTask(action); 

    ShowDialog(); 
} 

private void RunTask(Action action) 
{ 
    Task.Factory.StartNew(action).ContinueWith(_ => _currentTask.OnCompleted(null)); 
} 

private void Close(object state) 
{ 
    Debug.WriteLine(":: Close in thread: {0}", Thread.CurrentThread.ManagedThreadId); 

    Hide(); 
    Close(); 
} 
您可以看到,_currentTask.OnCompletednull是从另一个线程调用的,但是_currentTask类型Progress使用UI线程中捕获的上下文,但是OnCompletednull始终是从UI线程以外的另一个线程调用的。为什么?它必须在相同的上下文中

更新1:

将System.Threading.SynchronizationContext与System.Windows.Form.WindowsFormsSynchronizationContext和System.Windows.Threading.DispatchersSynchronizationContext混合使用

AsyncOperationManager的工作方式因调用AsyncOperationManager.CreateOperation的上下文而异。 根据上下文,AsyncOperationManager.CreateOperation可以创建三个上下文:

System.Threading.SynchronizationContext System.Windows.Form.WindowsFormsSynchronizationContext系统.Windows.Threading.DispatchersSynchronizationContext

在我的例子中,当我在ShowDialog之前捕获上下文时,我捕获线程同步上下文, 但如果在OnLoad事件中调用AsyncOperationManager.CreateOperation,则捕获 System.Windows.Form.WindowsFormsSynchronizationContext或DispatcherSynchronizationContext 根据Windows的不同,将使用窗体或WPF。这就是错误的根源

我会把它简化为只使用Dispatcher.BeginInvoke。
但是为了让所有的代码保持进度,我只是将AsyncOperationManager.CreateOperation和创建新的后台线程放在了OnLoad的ProgressWindowUI中。它已解决问题。

您正在从后台线程调用ContinueWith。为什么您认为它会将其封送到UI线程?因为在ProgressWindow的范围内,我创建了进度,其中我使用AsyncOperationManager.CreateOperation创建了asyncOperation。我用asyncOperation.Post调用OnCompleted。当然,这是相同的UI上下文。。。我想是的。Dispatcher.BeginInvoke解决了所有问题,但我想知道为什么这里缺少SynchronizationContext?不确定,不熟悉AsyncOperationManager。
private void RunTask(Action action) 
{ 
    Task.Factory.StartNew(action).ContinueWith(_ => _currentTask.OnCompleted(null)); 
}