2011-03-23 79 views
3

我看到围绕这一话题进行一些讨论,认为这是不可能的。我应该使用线程,使它成为STA,当我需要返回结果时,将主线程与创建的线程连接起来。这可以工作,但它不是一个理想的解决方案,因为使用委托我可以实现纯异步行为(使用回调)。所以,在我开始实现我自己的Future类之前(如在Java中);有没有更好的方式来实现这个使用代表?如何使代表线程STA


    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 
    } 

回答

4

这是不可能的。委托的BeginInvoke()方法始终使用线程池线程。 TP线程始终是MTA,不能更改。为了得到一个STA线程,你必须创建一个线程并启动它之前调用它SetApartmentState()方法。这个线程还必须抽取一个消息循环,Application.Run()。 COM对象只在其实例在该线程中创建时才使用它。

不知道你正在尝试做的,但如果想要多线程的代码不是线程安全的就不能正常工作一大块。 COM强制执行该操作。

+0

其实,我想从我的WinForm应用程序访问华廷的API。几乎所有由Watin公开的API都需要在STA中进行。我想在与主UI线程不同的线程中打开一个IE窗口。 – karephul 2011-03-23 18:16:09

+0

检查这个答案:http://stackoverflow.com/questions/4269800/c-webbrowser-control-in-a-new-thread/4271581#4271581 – 2011-03-23 18:19:19

+0

哦,谢谢!汉斯这几乎是我一直在寻找.. :)所以我使用线程,将它设置为STA和定义事件,使其纯异步(回调).. C#岩石 – karephul 2011-03-23 20:49:42

相关问题