在.NET Windows服务消息泵 [英] Message pump in .NET Windows service

查看:384
本文介绍了在.NET Windows服务消息泵的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我有一个Windows服务在C#编写处理我们所有的外部硬件的I / O亭应用。我们的一个新的设备是配备在本机DLL中的API USB设备。我有一个适当的P / Invoke包装类创建。但是,此API必须用HWND到Windows应用程序初始化,因为它使用消息泵来提高异步事件。

I have a Windows Service written in C# that handles all of our external hardware I/O for a kiosk application. One of our new devices is a USB device that comes with an API in a native DLL. I have a proper P/Invoke wrapper class created. However, this API must be initialized with an HWnd to a windows application because it uses the message pump to raise asynchronous events.

另外投入要求硬件制造商,为我们提供了不依赖于Windows消息泵的API,是有什么办法可以手动实例在我的Windows服务一个新的线程消息泵,我可以通过这个API?我是不是真的要创建一个完整的应用程序类,或者是有一个封装了消息泵水平较低.NET类?

Besides putting in a request to the hardware manufacturer to provide us with an API that does not depend on a Windows message pump, is there any way to manually instantiate a message pump in a new thread in my Windows Service that I can pass into this API? Do I actually have to create a full Application class, or is there a lower level .NET class that encapsulates a message pump?

推荐答案

感谢所有为您的建议。理查德放大器; overslacked,你在评论中提供的链接是非常有益的。另外,我没有让服务以手动启动与Application.Run消息泵与桌面交互。很显然,你只需要允许,如果你想让Windows自动启动一个消息泵为你的服务与桌面交互。

Thanks all for your suggestions. Richard & overslacked, the link you provided in the comments was very helpful. Also, I did not have to allow the service to interact with the desktop in order to manually start a message pump with Application.Run. Apparently, you only need to allow the service to interact with the desktop if you want Windows to start a message pump automatically for you.

有关每个人的熏陶,这里是我最后做手动启动该第三方API消息泵:

For everyone's edification, here is what I ended up doing to manually start a message pump for this 3rd party API:

internal class MessageHandler : NativeWindow
{
    public event EventHandler<MessageData> MessageReceived;

    public MessageHandler ()
    {
        CreateHandle(new CreateParams());
    }

    protected override void WndProc(ref Message msg)
    {
        // filter messages here for your purposes

        EventHandler<MessageData> handler = MessageReceived;
        if (handler != null) handler(ref msg);

        base.WndProc(ref msg);
    }
}

public class MessagePumpManager
{
    private readonly Thread messagePump;
    private AutoResetEvent messagePumpRunning = new AutoResetEvent(false);

    public StartMessagePump()
    {
        // start message pump in its own thread
        messagePump = new Thread(RunMessagePump) {Name = "ManualMessagePump"};
        messagePump.Start();
        messagePumpRunning.WaitOne();
    }

    // Message Pump Thread
    private void RunMessagePump()
    {
        // Create control to handle windows messages
        MessageHandler messageHandler = new MessageHandler();

        // Initialize 3rd party dll 
        DLL.Init(messageHandler.Handle);

        Console.WriteLine("Message Pump Thread Started");
        messagePumpRunning.Set();
        Application.Run();
    }
}

我必须克服一些障碍得到这个工作。其中之一是,你需要做一定的创造上执行Application.Run同一个线程的形式。你也只能从同一个线程访问Handle属性,所以我发现最容易简单地初始化该线程的DLL也是如此。据我所知,这是希望从一个GUI线程反正初始化。

I had to overcome a few hurdles to get this to work. One is that you need to make certain to create the Form on the same thread that you execute Application.Run. You also can only access the Handle property from that same thread, so I found it easiest to simply initialized the DLL on that thread as well. For all I know, it is expecting to be initialized from a GUI thread anyway.

此外,在我的实现中,MessagePumpManager类是一个Singleton实例,因此,只有一个消息泵运行了我的设备类的所有实例。请确保你真的,如果你启动线程在构造函数懒初始化一个实例。如果从静态的背景下启动线程(如私有静态MessagePumpManager实例=新MessagePumpManager())。运行时永远不会上下文切换到新创建的线程,你会死锁在等待消息泵启动

Also, in my implementation, the MessagePumpManager class is a Singleton instance, so that only one message pump runs for all instances of my device class. Make sure that you truly lazy-initialize your singleton instance if you start the thread in your constructor. If you start the thread from a static context (such as private static MessagePumpManager instance = new MessagePumpManager();) the runtime will never context switch into the newly created thread, and you will deadlock while waiting for the message pump to start.

这篇关于在.NET Windows服务消息泵的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

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