简体   繁体   English

事件在Windows Service中不起作用

[英]Events not working in Windows Service

I've created a managing application. 我已经创建了一个管理应用程序。 On of the things my application does, is register on a plugin which can detect whenever or not a fingerprint reader gets plugged in or plugged out. 我的应用程序要做的事情就是在一个插件上注册,该插件可以检测到何时插入或拔出指纹读取器。 The class subscribes on the event like such: 该类订阅事件,例如:

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

First when I was actively working on the program, I've developed a WPF application. 首先,当我积极从事该程序时,我已经开发了WPF应用程序。 Through this application I could see some of the lists and switch some settings so I am sure my service works well. 通过此应用程序,我可以看到一些列表并切换了一些设置,因此我确信我的服务运行良好。 In this WPF application, I've created my service by instantiating it: 在此WPF应用程序中,我通过实例化它来创建我的服务:

ProjectServiceLogic logic = new ProjectServiceLogic();

Now I've created an installer. 现在,我已经创建了一个安装程序。 Thus I had a ProjectService-class, initializing the application. 因此,我有一个ProjectService类,用于初始化应用程序。 This is being done like so: 这样做是这样的:

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))
    {

    }
}

The program gets installed and the service starts. 程序被安装并且服务开始。 When debugging the service, I notice the subscribing code gets executed. 调试服务时,我注意到订阅代码已执行。 However, the events are not triggered when I plug in a device while it does trigger when running it locally through the WPF application, instantiating the service logic. 但是,插入设备时不会触发事件,而通过WPF应用程序在本地运行该设备时会触发该事件,从而实例化服务逻辑。 Why doesn't it work now? 为什么现在不起作用?

_worker.SetApartmentState(ApartmentState.STA);

Selecting a Single Threaded Apartment requires you to implement the contract of an STA thread. 选择单线程单元需要您实施STA线程的协定。 Just two basic requirements: you can never block the thread and you must pump a message loop. 仅有两个基本要求:您永远不能阻塞线程,并且必须泵送消息循环。 The message loop is essential to allow COM to provide the guarantee that method calls on the COM object are always made from the thread that created the object, thus ensuring thread-safety. 消息循环对于使COM提供保证,保证对COM对象的方法调用始终是由创建该对象的线程进行的,从而确保线程安全。 Also the mechanism in .NET that makes Control.BeginInvoke and Dispatcher.BeginInvoke work. 也是.NET中使Control.BeginInvoke和Dispatcher.BeginInvoke起作用的机制。

A COM component counts on having that guarantee in place, it often relies on the message dispatcher to take care of its own inter-thread marshaling. COM组件指望有适当的保证,它通常依赖消息分发程序来照顾自己的线程间编组。 Like Dispatcher.BeginInvoke does. 就像Dispatcher.BeginInvoke一样。

Two things go wrong when you don't in fact pump a message loop as required. 当您实际上没有按要求抽送消息循环时,有两件事会出错。 First of all, as expected, any calls you make on the object from a worker thread will deadlock. 首先,正如预期的那样,您从工作线程对该对象进行的任何调用都会死锁。 COM will use PostMessage to ask the STA thread to dispatch the call. COM将使用PostMessage来请求STA线程调度该调用。 But that won't happen when the thread isn't retrieving messages from the message queue. 但是,如果线程不从消息队列中检索消息,则不会发生这种情况。 Second thing that goes wrong is likely what you see happening here, the component itself uses PostMessage to raise events on the STA thread. 第二件事出了问题,很可能是您在这里看到的情况,该组件本身使用PostMessage在STA线程上引发事件。 With the failure mode that the event is never raised. 在失败模式下,事件永远不会引发。 Also classically the way WebBrowser misbehaves, you never get the DocumentCompleted event. 同样,按照传统的WebBrowser行为方式,您永远不会获得DocumentCompleted事件。

You'll need to pump a message loop, Application.Run(). 您需要添加一个消息循环Application.Run()。 Either the Winforms or the WPF version of it will do, take your pick. 无论是Winforms还是WPF版本,都可以选择。 A Winforms example is here Winforms示例在这里

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM