没有第二种形式的多线程消息泵送

发布于 2024-08-05 00:21:12 字数 662 浏览 2 评论 0原文

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

因此,我想将 COM 组件托管在它自己的 Application.Run() 内的自己的线程上,但我无法弄清楚如何在不创建 UI 表单的情况下在新线程上开始工作。

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

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

I have a C# application which uses a COM component. This COM component require a message pump (Application.Run()) to do its processing. This means it's been stuck on the main thread. But I recently discovered that it's possible to start another Application.Run on another thread which gets its own ApplicationContext.

So I want to host the COM component on its own thread inside it's own Application.Run(), but I can't figure out how to get things started on the new thread without creating a UI form.

The WindowsFormsSynchronizationContext I need to communicate with the thread doesn't get created until Application.Run(). But once Application.Run() is called, I can't figure out how to get at the SynchronizationContext. If I could just raise a single event on that thread, I could use that to bootstrap the whole thing (create the COM object, etc.), but there doesn't seem to be anywhere to hook into the new event loop without a form.

I've tried all kinds of convoluted things, like installing a message filter (no messages get raised on the new thread), copying the execution context into another thread and trying to retrieve the SynchronizationContext from there (it refuses to copy the ExecutionContext of an already running thread), retrieving Thread.CurrentContext before starting Application.Run() and then calling DoCallbBack() (the DoCallback ends up on the original thread), etc. Nothing I've tried works.

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(1

雨后彩虹 2024-08-12 00:21:12

Bryce,

您也许可以改编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 分钟内。

Bryce,

You might be able to adapt this snippet from Anders Hejlsberg's talk about "The Future of C#". It's a little class that adds a message pump to a thread so that he can open windows using a REPL loop, and they will have a message pump attached to them.

The code looks like this:

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);
    }
}

The discussion relating to this code occurs at 1 hour 5 minutes into Anders' talk, if you want to review it.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文