如何将委托线程设置为STA

3

我看到了关于这个话题的一些讨论并得出结论,这是不可能的。我应该使用线程,并将其设置为STA,当我需要返回结果时,使用创建的线程与主线程连接。这可以工作,但不是理想的解决方案,因为使用委托我可以实现纯异步行为(使用回调)。因此,回到起点 - 在我开始实现自己的Future类之前(就像Java中的Future类);是否有更好的方法使用委托来实现这一点?


   private delegate String DelegateFoo(String[] input);
   private String Foo(String[] input){
      // do something with input
      // this code need to be STA
      // below code throws exception .. that operation is invalid
      // Thread.CurrentThread.SetApartmentState(ApartmentState.STA)
      return "result";
   }

   private void callBackFoo(IAsyncResult iar){
      AsyncResult result = (AsyncResult)iar;
      DelegateFoo del = (DelegateFoo)result.AsyncDelegate;
      String result = null;
      try{
          result = del.EndInvoke(iar);
      }catch(Exception e){
          return;        
      }

      DelegateAfterFooCallBack callbackDel = new DelegateAfterFooCallBack (AfterFooCallBack);
      // call code which should execute in the main UI thread.
      if (someUIControl.InvokeRequired)
      {   // execute on the main thread.
         callbackDel.Invoke();
      }
      else 
      {
         AfterFooCallBack();
      }
   }
   private void AfterFooCallBack(){
       // should execute in main UI thread to update state, controls and stuff
   }

1个回答

5

这是不可能的。委托的BeginInvoke()方法总是使用线程池线程。而TP线程始终为MTA,无法更改。要获取STA线程,必须创建一个线程并在启动之前调用其SetApartmentState()方法。此线程还必须泵送消息循环Application.Run()。COM对象仅在其实例在该线程中创建时使用它。

不确定您想要做什么,但尝试多线程执行不安全的代码块是行不通的。COM会强制执行此操作。


实际上,我想从我的Winform应用程序中访问Watin API。 Watin公开的几乎所有API都需要线程处于STA状态。我想在与我的主UI线程不同的线程中打开一个IE窗口。 - karephul
请查看此答案:https://dev59.com/FW855IYBdhLWcg3wj1MS#4271581 - Hans Passant
哦,谢谢Hans!! 那几乎就是我在寻找的了.. :) 所以我正在使用线程,将其设置为STA并定义一个事件使其纯异步(带回调).. C#很棒。 - karephul

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接