使用命名事件进行进程间通信 [英] Using Named events for inter process communication

查看:165
本文介绍了使用命名事件进行进程间通信的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我需要使用自动重置事件和手动重置事件等命名事件将通知事件从Windows服务发送到Windows控制台/窗体应用程序。为此我创建了一个类库(WaitHandler),它具有Events的定义。 Windows客户端和服务都已由声明事件的类库引用。 Windows客户端等待WaitOne(),服务需要引发一个Set事件,以便Windows客户端代码可以进入循环。但是当我尝试提高Set事件时,我的客户端没有收到它。



I have a requirement to send notification events from Windows Service to a Windows console/Forms application using Named Events like Auto Reset Events and Manual reset events. For which I created a class library (WaitHandler) which has the definition for the Events. The windows client and service both have been reference by the class library in which the events are declared. The windows client waits at WaitOne() and the service need to raise an Set event so that windows client code can get into the loop. But When I try to raise the Set event, my client is not receiving it.

public static class WaitHandler
    {
        private static System.Threading.ManualResetEvent manual = new     System.Threading.ManualResetEvent(false);
        private static System.Threading.AutoResetEvent auto = new   System.Threading.AutoResetEvent(false);

       public static System.Threading.AutoResetEvent GetAutoEventHandler()
       {
        return auto;
       }

    public static System.Threading.ManualResetEvent  GetManualEventHandler()
    {
        return manual;
    }
}





这是我在Windows服务中的代码:





This is my code in Windows Service:

public void RaiseEvent()
{
  WaitHandler.GetManualEventHandler().Set();
}





这是我在Windows客户端的代码:





This is my code in Windows Client:

public Form1()
   {
       InitializeComponent();
       new Task((o) => SubscribeToAsyncEvents(),
           new System.Threading.CancellationToken()).Start();
   }

   private void SubscribeToAsyncEvents()
   {
       while (true)
       {
           if (WaitHandler.GetManualEventHandler().WaitOne())
           {
               Console.WriteLine("Received Event");
               WaitHandler.GetManualEventHandler().Reset();
           }
       }

   }





谢谢



Thanks

推荐答案

您严重滥用事件等待句柄对象。这些事件仅用于通知处于等待状态的线程,以将其唤醒。实际上,这不是你可以发送和接收的意义上的事件,这是一种限制某些线程执行而不浪费CPU时间的方法(就像旋转等待时一样):等待事件等待处理程序对象的线程被切换出来,并且在被另一个线程设置的事件等待处理程序唤醒之前不会被调度回执行。它也可以用于线程同步,使一个线程等待另一个线程完成某些工作。作为所有阻塞调用,它应该在应用程序生命周期中充分考虑和理论计算。



此外,在唤醒后立即手动重置(或几乎,如在你的情况)可以被视为另一种滥用。 (但这取决于你试图实现的目标。)你可以使用 System.Threading.AutoResetEvent 。功能与您看似模拟的自动重置功能不同。无法保证模拟 AutoResetEvent 的重置与 ManualResetEvent 重置:自动重置机制保证只有一个线程在一个时间通过线程被唤醒时的点;第二个线程将再次被阻止。



您的静态类工厂方法是完全冗余的:如果您想根据条件选择自动或手动复位,您可以使用基类 System.Threading.EventWaitHandle 并使用其构造函数控制重置类型,其中一个构造函数使用 EventResetMode 参数: https://msdn.microsoft.com /en-us/library/system.threading.eventwaithandle%28v=vs.110%29.aspx



您的 RaiseEvent 方法是正确的(但是,不清楚为什么要编写一个单独的方法,但它没关系),但是你没有显示你调用它的位置。它会真正唤醒在等待事件等待处理程序时阻塞的线程。这一切都取决于你什么时候打电话。但主要的是:没有收到这种事件。



另见我过去对这个主题的答案以及这些课程的目的:

线程中的ManualResetEvent和AutoResetEvent

暂停正在运行的主题

使代码线程安全。,

在webservice中正好运行一个作业/线程/进程永远不会被终止(asp.net) ..



现在,这些类主要用于同一进程的线程的线程同步。对于IPC,有许多不同的设施。我想提一个经常被遗忘的东西:插座。请记住,从历史上看,套接字纯粹是作为IPC工具开发的,后来才用于网络。这仍然是一个非常好的和灵活的IPC工具。请参阅:

https ://msdn.microsoft.com/en-us/library/system.net.sockets%28v=vs.110%29.aspx



-SA
You are badly misusing the event wait handle objects. These events are used only to notify the thread in a wait state, to wake it up. Actually, this is not an "event" in the sense of something you can "send" and "receive", this is a way to throttle execution of some thread without any waste of CPU time (as it happens with spin wait): the thread waiting for the event wait handler object is switched out and is not scheduled back to execution until it is waken up by the event wait handler set by another thread. It also can be used for thread synchronization, to make one thread waiting for another thread to complete some part of work. As all blocking call, it should be used with great consideration and theoretical calculations of the application lifetime.

Also, manual reset right after waking up (or almost, as in your case) can be considered as another abuse. (But it depends on what you try to achieve.) You could use System.Threading.AutoResetEvent. The functionality is no the same as in your seemingly "simulated" auto reset. It is impossible to guarantee simulation AutoResetEvent's reset with ManualResetEvent reset: auto resetting mechanism guarantees that exactly one thread at a time is passed through the point when the thread is waken up; the second thread will be always blocked again.

Your static class-factory methods are totally redundant: if you want to choose auto or manual reset depending on condition, you could use the base class System.Threading.EventWaitHandle and control the type of reset using its constructor, one of the constructors using EventResetMode argument: https://msdn.microsoft.com/en-us/library/system.threading.eventwaithandle%28v=vs.110%29.aspx.

Your RaiseEvent method is correct (however, it's not clear why writing a separate method, but it's OK), but you did not show where you called it. It will really wake up the thread blocked at the wait for the event wait handler. It all depends on when you call it. But main thing is: there is no such thing as "receive" this kind of event.

See also my past answers on this topic and on the purpose of these classes:
ManualResetEvent and AutoResetEvent in Thread,
pause running thread,
Making Code Thread Safe.,
Running exactly one job/thread/process in webservice that will never get terminated (asp.net)..

Now, these classes are mostly used for thread synchronization for the threads of the same process. For IPC, there are many different facilities. I would like to mention one which is often forgotten: sockets. Remember that, historically, sockets have been developed purely as IPC facility, only later used for networking. This is still a very good and flexible IPC tool. Please see:
https://msdn.microsoft.com/en-us/library/system.net.sockets%28v=vs.110%29.aspx.

—SA


这是使用EventWaitHandle实现多个进程之间同步的解决方案。我发布它以便它可能对其他人有用。



使用以下两个链接来完成从Windows服务通知客户端应用程序的任务。使用下面的内容后,请确保在创建事件时使用Global\前缀,因为Windows服务在会话0中运行,而用户应用程序在会话1或更高版本中运行。因此,对于服务和用户应用程序进行通信,他们必须使用全球物品。



http://blogs.msdn.com/b/mattdotson/archive/2006/03/03/543143.aspx [ ^ ]



https://msdn.microsoft.com/en-us/library/z4c9z2kt (v = vs.110).aspx [ ^ ]
Here is the solution using the EventWaitHandle to achieve synchronization between multiple processes. I am posting it so that it could be helpful to somebody else.

Used the below two links to achieve the task of notifying client application from a windows service. After using the below, please make sure to use the 'Global\" prefix while creating the event as the Windows Services run in session 0, and user applications run in session 1 or higher. So for a service and a user application to communicate, they must use global objects.

http://blogs.msdn.com/b/mattdotson/archive/2006/03/03/543143.aspx[^]

https://msdn.microsoft.com/en-us/library/z4c9z2kt(v=vs.110).aspx[^]


这篇关于使用命名事件进行进程间通信的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

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