gpt4 book ai didi

c# - 如何以编程方式退出第二个消息循环?

转载 作者:太空狗 更新时间:2023-10-30 01:10:23 26 4
gpt4 key购买 nike

我正在尝试创建第二个消息循环以在 C# 中异步处理/过滤低级消息。它的工作原理是创建一个隐藏窗体,公开要 Hook 的 Handle 属性,并在单独的线程中运行第二个消息循环。目前我对结果很满意,但我无法正确退出第二个循环。唯一的解决方法是将 IsBackground 属性设置为 true,这样第二个线程将在主应用程序退出时简单地终止(不处理所有未决消息)。

问题是:如何正确退出该消息循环以便第二个 Application.Run() 返回?我尝试了不同的方法来创建单独的 ApplicationContext 并控制各种事件(Application.ApplicationExit、Application.ThreadExit、ApplicationContext.ThreadExit),但它们都因我无法调试的竞争条件而失败。

有什么提示吗?谢谢

这是代码:

public class MessagePump
{
public delegate void HandleHelper(IntPtr handle);

public MessagePump(HandleHelper handleHelper, Filter filter)
{
Thread thread = new Thread(delegate()
{
ApplicationContext applicationContext = new ApplicationContext();
Form form = new Form();
handleHelper(form.Handle);
Application.AddMessageFilter(new MessageFilter(filter));
Application.Run(applicationContext);
});
thread.SetApartmentState(ApartmentState.STA);
thread.IsBackground = true; // <-- The workaround
thread.Start();
}
}

public delegate bool Filter(ref Message m);

internal class MessageFilter : IMessageFilter
{
private Filter _Filter;

public MessageFilter(Filter filter)
{
_Filter = filter;
}

#region IMessageFilter Members

public bool PreFilterMessage(ref Message m)
{
return _Filter(ref m);
}

#endregion // IMessageFilter Members
}

我以这种方式在主 Form 构造函数中使用它:

_Completion = new ManualResetEvent(false);

MessagePump pump = new MessagePump(
delegate(IntPtr handle)
{
// Sample code, I did this form twain drivers low level wrapping
_Scanner = new TwainSM(handle);
_Scanner.LoadDs("EPSON Perfection V30/V300");
},
delegate(ref Message m)
{
// Asyncrhronous processing of the messages
// When the correct message is found -->
_Completion.Set();
}

编辑:我回答中的完整解决方案。

最佳答案

您应该将 Form 实例作为参数传递给 ApplicationContext 构造函数:

applicationContext = new ApplicationContext(form); 

现在,您基本上是在创建一个无上下文实例,它不关心您的表单是否被关闭。

此外,进行一些清理工作是一个很好的做法,例如在您不再需要过滤器时将其移除:

Form form = new Form();
ApplicationContext applicationContext = new ApplicationContext(form);
handleHelper(form.Handle);

MessageFilter filter = new MessageFilter(filter);
Application.AddMessageFilter(filter);
Application.Run(applicationContext);
Application.RemoveMessageFilter(filter);

[编辑]

如果您不想显示表单,那么您可以使用无参数构造器,但您必须通过调用 ApplicationContext.ExitThread 手动关闭上下文。方法。如果您在构造函数中传递表单,则当您的表单触发 FormClosed 事件时,实际上会调用此方法。

由于隐藏表单与上下文无关,所以你需要在某个时候将它们都退出。

关于c# - 如何以编程方式退出第二个消息循环?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/4815699/

26 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com