向 Windows 窗体消息循环发送或发布消息 [英] Send or post a message to a Windows Forms message loop
问题描述
我有一个线程从命名管道中读取消息.这是一个阻塞读取,这就是为什么它在自己的线程中.当此线程读取消息时,我希望它通知主线程中运行的 Windows 窗体消息循环消息已准备就绪.我怎样才能做到这一点?在 win32 中,我会执行 PostMessage,但该功能在 .Net 中似乎不存在(或者至少我找不到).
I have a thread that reads messages from a named pipe. It is a blocking read, which is why it's in its own thread. When this thread reads a message, I want it to notify the Windows Forms message loop running in the main thread that a message is ready. How can I do that? In win32 I would do a PostMessage, but that function does not seem to exist in .Net (or at least I could not find it).
推荐答案
在 WinForms 中,您可以通过 Control.BeginInvoke.一个例子:
In WinForms you can achieve this with Control.BeginInvoke. An example:
public class SomethingReadyNotifier
{
private readonly Control synchronizer = new Control();
/// <summary>
/// Event raised when something is ready. The event is always raised in the
/// message loop of the thread where this object was created.
/// </summary>
public event EventHandler SomethingReady;
protected void OnSomethingReady()
{
SomethingReady?.Invoke(this, EventArgs.Empty);
}
/// <summary>
/// Causes the SomethingReady event to be raised on the message loop of the
/// thread which created this object.
/// </summary>
/// <remarks>
/// Can safely be called from any thread. Always returns immediately without
/// waiting for the event to be handled.
/// </remarks>
public void NotifySomethingReady()
{
this.synchronizer.BeginInvoke(new Action(OnSomethingReady));
}
}
上述不依赖于 WinForms 的更简洁的变体是使用 SynchronizationContext
.在主线程上调用 SynchronizationContext.Current,然后将该引用传递给如下所示的类的构造函数.
A cleaner variant of the above which doesn't depend on WinForms would be to use SynchronizationContext
. Call SynchronizationContext.Current on your main thread, and then pass that reference to the constructor of the class shown below.
public class SomethingReadyNotifier
{
private readonly SynchronizationContext synchronizationContext;
/// <summary>
/// Create a new <see cref="SomethingReadyNotifier"/> instance.
/// </summary>
/// <param name="synchronizationContext">
/// The synchronization context that will be used to raise
/// <see cref="SomethingReady"/> events.
/// </param>
public SomethingReadyNotifier(SynchronizationContext synchronizationContext)
{
this.synchronizationContext = synchronizationContext;
}
/// <summary>
/// Event raised when something is ready. The event is always raised
/// by posting on the synchronization context provided to the constructor.
/// </summary>
public event EventHandler SomethingReady;
private void OnSomethingReady()
{
SomethingReady?.Invoke(this, EventArgs.Empty);
}
/// <summary>
/// Causes the SomethingReady event to be raised.
/// </summary>
/// <remarks>
/// Can safely be called from any thread. Always returns immediately without
/// waiting for the event to be handled.
/// </remarks>
public void NotifySomethingReady()
{
this.synchronizationContext.Post(
state => OnSomethingReady(),
state: null);
}
}
这篇关于向 Windows 窗体消息循环发送或发布消息的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!