4

我有一个使用 COM 组件的 C# 应用程序。这个 COM 组件需要一个消息泵 (Application.Run()) 来完成它的处理。这意味着它被卡在主线程上。但我最近发现可以在另一个线程上启动另一个 Application.Run,​​它有自己的 ApplicationContext。

所以我想将 COM 组件托管在它自己的 Application.Run() 内的自己的线程上,但我不知道如何在不创建 UI 表单的情况下在新线程上开始工作。

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

我已经尝试过各种复杂的事情,比如安装消息过滤器(在新线程上不会引发任何消息),将执行上下文复制到另一个线程并尝试从那里检索 SynchronizationContext(它拒绝复制 ExecutionContext已经运行线程),在启动 Application.Run() 然后调用 DoCallbBack() 之前检索 Thread.CurrentContext (DoCallback 最终在原始线程上)等等。我尝试过的没有任何效果。

4

1 回答 1

7

布莱斯,

您或许可以从Anders Hejlsberg 关于“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);
    }
}

与此代码相关的讨论发生在 Anders 演讲的 1 小时 5 分钟后,如果您想查看它。

于 2009-09-15T16:43:24.037 回答