如何发布消息运行一个消息泵STA线程? [英] How to post messages to an STA thread running a message pump?

查看:172
本文介绍了如何发布消息运行一个消息泵STA线程?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

所以,下面的,我决定明确实例化一个专用的STA线程COM对象。实验表明,COM对象需要一个消息泵,这是我通过调用创建 Application.Run()

So, following this, I decided to explicitly instantiate a COM object on a dedicated STA thread. Experiments showed that the COM object needed a message pump, which I created by calling Application.Run():

private MyComObj _myComObj;

// Called from Main():
Thread myStaThread = new Thread(() =>
{
    _myComObj = new MyComObj();
    _myComObj.SomethingHappenedEvent += OnSomthingHappened;
    Application.Run();
});
myStaThread.SetApartmentState(ApartmentState.STA);
myStaThread.Start();

我如何发帖免受其他线程STA线程的消息泵?

How do I post messages the the STA thread's message pump from other threads?

注意:
我大量编辑为简洁起见的问题。动@ Servy的回答现在看来不相关的某些部分,但他们对原来的问题。

Note: I heavily edited the question for the sake of brevity. Some parts of @Servy's answer now seems unrelated, but they were for the original question.

推荐答案

记住,那Windows创建一个STA线程消息队列已经是线程安全队列的实现。因此,只要用它自己的目的。下面是一个基类,你可以使用,派生自己,包括你的COM对象。重写初始化()方法,将尽快称为线程准备开始执行code。不要忘记调用base.Initialize()在你的覆盖。

Keep in mind that the message queue that Windows creates for an STA thread is already an implementation of a thread-safe queue. So just use it for your own purposes. Here's a base class that you can use, derive your own to include your COM object. Override the Initialize() method, it will be called as soon as the thread is ready to start executing code. Don't forget to call base.Initialize() in your override.

这要在该线程运行code再使用的BeginInvoke或调用方法,就像你会为Control.Begin /调用或Dispatcher.Begin / Invoke的方法。其调用Dispose()方法关闭线程,它是可选的。

It you want to run code on that thread then use the BeginInvoke or Invoke methods, just like you would for the Control.Begin/Invoke or Dispatcher.Begin/Invoke methods. Call its Dispose() method to shut down the thread, it is optional.

using System;
using System.Threading;
using System.Windows.Forms;

class STAThread : IDisposable {
    public STAThread() {
        using (mre = new ManualResetEvent(false)) {
            thread = new Thread(() => {
                Application.Idle += Initialize;
                Application.Run();
            });
            thread.IsBackground = true;
            thread.SetApartmentState(ApartmentState.STA);
            thread.Start();
            mre.WaitOne();
        }
    }
    public void BeginInvoke(Delegate dlg, params Object[] args) {
        if (ctx == null) throw new ObjectDisposedException("STAThread");
        ctx.Post((_) => dlg.DynamicInvoke(args), null);
    }
    public object Invoke(Delegate dlg, params Object[] args) {
        if (ctx == null) throw new ObjectDisposedException("STAThread");
        object result = null;
        ctx.Send((_) => result = dlg.DynamicInvoke(args), null);
        return result;
    }
    protected virtual void Initialize(object sender, EventArgs e) {
        ctx = SynchronizationContext.Current;
        mre.Set();
        Application.Idle -= Initialize;
    }
    public void Dispose() {
        if (ctx != null) {
            ctx.Send((_) => Application.ExitThread(), null);
            ctx = null;
        }
    }
    private Thread thread;
    private SynchronizationContext ctx;
    private ManualResetEvent mre;
}

这篇关于如何发布消息运行一个消息泵STA线程?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆