C# 使用同步上下文在同一UI线程中完成操作
我想从UI线程1创建一个进度UIthread2。 进度UI在thread3中创建任务并等待其完成 taskthread3完成并调用必须在thread2中执行的进程UI的关闭 对于关闭操作,我使用AsyncOperationManager捕获thread2的上下文,然后从thread4执行POST方法 但是关闭总是从另一个线程发生 下面的所有代码都来自ProgressWindows类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
_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));
}