2009-09-15 89 views
4

我有一个使用COM组件的C#应用​​程序。这个COM组件需要一个消息泵(Application.Run())来处理它。这意味着它一直卡在主线程上。但是我最近发现可以在另一个获得自己的ApplicationContext的线程上启动另一个Application.Run。没有第二种形式的多线程消息抽取

所以我想在它自己的Application.Run()中的自己的线程上承载COM组件,但我无法弄清楚如何在不创建UI表单的情况下在新线程上启动事物。

我需要与线程通信的WindowsFormsSynchronizationContext直到Application.Run()才被创建。但是一旦调用了Application.Run(),我就无法弄清楚如何获取SynchronizationContext。如果我可以在该线程上引发单个事件,那么我可以使用它来引导整个事物(创建COM对象等),但似乎没有任何地方可以在没有表单的情况下挂入新的事件循环。

我已经尝试过各种令人费解的事情,比如安装一个消息过滤器(在新线程中没有提示消息),将执行上下文复制到另一个线程中并尝试从那里检索SynchronizationContext(它拒绝复制一个已经运行的线程的ExecutionContext),在启动Application.Run()之前检索Thread.CurrentContext,然后调用DoCallbBack()(DoCallback在原始线程上结束)等等。

回答

6

布莱斯,

您也许能够从Anders Hejlsberg's talk about "The Future of C#".适应这个片段中这是一个有点类,增加了一个消息泵线程,这样他就可以使用REPL循环打开的窗户,他们将有一个消息泵附在他们身上。

的代码看起来是这样的:

using System.Windows.Forms; 
using System.Threading; 
class UserInterfaceThread() 
{ 
    static Form window; 

    public UserInterfaceThread() 
    { 
     var thread = new Thread(() => { 
      window = new Form(); 
      var handle = window.Handle; 
      Application.Run(); 
      }); 
     thread.Start(); 
    } 
    public void Run(Action action) 
    { 
     window.Invoke(action); 
    } 
} 

与此代码的讨论发生后1小时到Anders的通话5分钟,如果你想查看。

+0

所以事实证明,创建一个窗口句柄是实例化SynchronizationContext而不是Application.Run()。所以简单地调用“IntPtr handle = new Form()。Handle;”在调用Application.Run()之前创建所需的WindowsFormsSynchronizationContext。非常感谢。 – 2009-09-15 17:02:09