如何在STA线程中运行一些东西?

在我的WPF应用程序中,我做了一些asynchronous通信(与服务器)。 在callback函数中,我最终从服务器的结果中创buildInkPresenter对象。 这要求正在运行的线程是STA,显然它现在不是。 因此,我得到以下例外:

无法在程序集[..]中创build'InkPresenter'实例。调用线程必须是STA,因为许多UI组件都需要这个。

目前我的asynchronous函数调用是这样的:

public void SearchForFooAsync(string searchString) { var caller = new Func<string, Foo>(_patientProxy.SearchForFoo); caller.BeginInvoke(searchString, new AsyncCallback(SearchForFooCallbackMethod), null); } 

我如何使callback – 这将做InkPresenter创build – 是STA? 或者在新的STA线程中调用XamlReaderparsing。

 public void SearchForFooCallbackMethod(IAsyncResult ar) { var foo = GetFooFromAsyncResult(ar); var inkPresenter = XamlReader.Parse(foo.Xaml) as InkPresenter; // <!-- Requires STA [..] } 

你可以像这样启动STA线程:

  Thread thread = new Thread(MethodWhichRequiresSTA); thread.SetApartmentState(ApartmentState.STA); //Set the thread to STA thread.Start(); thread.Join(); //Wait for the thread to end 

唯一的问题是你的结果对象必须以某种方式传递。你可以使用私有字段,或者潜入parameter passing到线程。 在这里,我将foo数据设置在一个专用字段中,并启动STA线程来改变inkPresenter!

 private var foo; public void SearchForFooCallbackMethod(IAsyncResult ar) { foo = GetFooFromAsyncResult(ar); Thread thread = new Thread(ProcessInkPresenter); thread.SetApartmentState(ApartmentState.STA); thread.Start(); thread.Join(); } private void ProcessInkPresenter() { var inkPresenter = XamlReader.Parse(foo.Xaml) as InkPresenter; } 

希望这可以帮助!

您可以使用Dipatcher类在UI线程上执行方法调用。 Dispatcher提供静态属性CurrentDispatcher来获取线程的调度程序。

如果创buildInkPresenter的类的对象是在UI线程上创build的,则CurrentDispatcher方法将返回UI线程的Dispatcher。

在Dispatcher上,您可以调用BeginInvoke方法在线程上asynchronous调用指定的委托。

在UI线程上调用它应该足够好。 因此,使用BackgroundWorker并在RunWorkerAsyncCompleted ,然后可以创buildinkPresenter。

这是一个黑客,但我会使用XTATestRunner所以你的代码将如下所示:

  public void SearchForFooAsync(string searchString) { var caller = new Func<string, Foo>(_patientProxy.SearchForFoo); caller.BeginInvoke(searchString, new AsyncCallback(SearchForFooCallbackMethod), null); } public void SearchForFooCallbackMethod(IAsyncResult ar) { var foo = GetFooFromAsyncResult(ar); InkPresenter inkPresenter; new XTATestRunner().RunSTA(() => { inkPresenter = XamlReader.Parse(foo.Xaml) as InkPresenter; }); } 

作为奖励,可以捕获在STA(或MTA)线程中抛出的exception,如下所示:

 try{ new XTATestRunner().RunSTA(() => { throw new InvalidOperationException(); }); } catch(InvalidOperationException ex){ }