事件在Windows服务中不起作用

本文关键字:不起作用 服务 Windows 事件 | 更新日期: 2023-09-27 18:12:41

我创建了一个管理应用程序。我的应用程序所做的一件事是注册一个插件,该插件可以检测指纹读取器何时插入或拔出。类订阅这样的事件:

//Subscribe to the plug, unplug and imageAcquired events from the GrFingerXCtrlClass library.
FingerXCtrlClass.SensorPlug += ReaderPlug;
FingerXCtrlClass.SensorUnplug += ReaderUnplug;
FingerXCtrlClass.ImageAcquired += ImageAcquired;

首先,当我积极参与该程序时,我开发了一个WPF应用程序。通过这个应用程序,我可以看到一些列表并切换一些设置,所以我确信我的服务运行良好。在这个WPF应用程序中,我通过实例化它创建了我的服务:

ProjectServiceLogic logic = new ProjectServiceLogic();

现在我已经创建了一个安装程序。因此,我有了一个ProjectService类,用于初始化应用程序。这是这样做的:

protected override void OnStart(string[] args)
{
    log.Debug("Starting service...");
    _worker = new Thread(new ThreadStart(StartService));
    _worker.IsBackground = true;
    _worker.Name = "ServiceThread";
    _worker.SetApartmentState(ApartmentState.STA);
    _worker.Start();
    log.Debug("Successfully started service");
}
void StartService()
{
    serviceLogic = new ProjectServiceLogic();
    while (!_shutdownEvent.WaitOne(0))
    {
    }
}

程序安装完毕,服务启动。在调试服务时,我注意到订阅代码被执行了。然而,当我插入设备时,事件不会被触发,而当它通过WPF应用程序在本地运行并实例化服务逻辑时,事件会被触发。为什么现在不起作用?

事件在Windows服务中不起作用

_worker.SetApartmentState(ApartmentState.STA);

选择单线程单元需要实现STA线程的合约。只有两个基本要求:永远不能阻塞线程,并且必须泵送一个消息循环。消息循环对于允许COM提供对COM对象的方法调用始终由创建对象的线程进行的保证至关重要,从而确保线程安全。还有.NET中使Control.BeginInvoke和Dispatcher.BeginInvoke工作的机制。

COM组件依赖于有适当的保证,它通常依赖于消息调度程序来处理自己的线程间封送处理。就像Dispatcher.BeginInvoke一样。

当您实际上没有根据需要泵送消息循环时,会出现两件事。首先,正如预期的那样,您从工作线程对对象进行的任何调用都将死锁。COM将使用PostMessage请求STA线程调度该调用。但是,当线程没有从消息队列中检索消息时,这种情况就不会发生。第二个问题可能是您在这里看到的情况,组件本身使用PostMessage在STA线程上引发事件。对于从不引发事件的故障模式。同样是典型的WebBrowser错误行为方式,您永远不会得到DocumentCompleted事件。

你需要启动一个消息循环Application.Run((。无论是Winforms还是WPF版本,你都可以选择。Winforms的例子是