作者热门文章
- android - RelativeLayout 背景可绘制重叠内容
- android - 如何链接 cpufeatures lib 以获取 native android 库?
- java - OnItemClickListener 不起作用,但 OnLongItemClickListener 在自定义 ListView 中起作用
- java - Android 文件转字符串
所以,关注 this ,我决定在专用 STA 线程上显式实例化一个 COM 对象。实验表明 COM 对象需要一个消息泵,这是我通过调用 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 线程的消息泵发布消息?
注意:为了简洁起见,我对问题进行了大量编辑。 @Servy 回答的某些部分现在看起来无关紧要,但它们是针对原始问题的。
最佳答案
请记住,Windows 为 STA 线程创建的消息队列已经是线程安全队列的实现。因此,只需将其用于您自己的目的即可。这是您可以使用的基类,派生您自己的基类以包含您的 COM 对象。覆盖 Initialize() 方法,一旦线程准备好开始执行代码,它就会被调用。不要忘记在覆盖中调用 base.Initialize()。
如果您想在该线程上运行代码,然后使用 BeginInvoke 或 Invoke 方法,就像您使用 Control.Begin/Invoke 或 Dispatcher.Begin/Invoke 方法一样。调用它的 Dispose() 方法来关闭线程,它是可选的。请注意,只有当您 100% 确定所有 COM 对象都已完成时,这样做才是安全的。由于您通常没有这种保证,所以最好不要。
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;
}
关于c# - 如何将消息发布到运行消息泵的 STA 线程?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/21680738/
我是一名优秀的程序员,十分优秀!