C# 等待EventWaitHandle.Set()之后通知的所有进程

C# 等待EventWaitHandle.Set()之后通知的所有进程,c#,concurrency,synchronization,interprocess,C#,Concurrency,Synchronization,Interprocess,我在一个过程中: 在另一个过程中: 但从未收到通知(没有控制台输出)。 似乎设置为异步 如何等待所有服务员收到信号后再执行重置()? 我创建等待句柄(名为进程间等待句柄): 更新 现在我有一个“解决方案” 第二种可能-每个进程都有多个句柄。但此代码应该适用于任何office应用程序加载项或独立应用程序。因此,应该以某种方式生成和发现名称 第三,使用WCF p2p(netPeerTcpBinding)或UdpDiscoveryEndpoint命名管道-但这些管道使用“IP”,因此在部署到最终用户时

我在一个过程中:

在另一个过程中:

但从未收到通知(没有控制台输出)。 似乎设置为异步

如何等待所有服务员收到信号后再执行重置()?

我创建等待句柄(名为进程间等待句柄):

更新

现在我有一个“解决方案”

第二种可能-每个进程都有多个句柄。但此代码应该适用于任何office应用程序加载项或独立应用程序。因此,应该以某种方式生成和发现名称


第三,使用WCF p2p(netPeerTcpBinding)或UdpDiscoveryEndpoint命名管道-但这些管道使用“IP”,因此在部署到最终用户时可能会出现一些安全问题?

是的,
Set()
函数会立即退出,因此调用
Set()
Reset()
基本上不会起任何作用,或者做一些随机的事情。您可以通过重置侦听线程上的事件来解决此问题,在执行
WaitOne()

之后,您可以将
EventResetMode
设置为
EventResetMode.AutoReset
,这样,当其中一个进程接收事件时,它将自动重置事件。之后,您不必手动重置它

有了多个进程,您可以为每个侦听器创建一个事件,并在必须发出事件信号时触发所有侦听器

foreach(var process in _myProcesses)
{
    waitHandles.Add(OpenExistingOrCreateEventWaitHandle(process.SharedWaitHandleName);
}

...

internal static EventWaitHandle OpenExistingOrCreateEventWaitHandle(string name)
{
    try
    {
        return EventWaitHandle.OpenExisting(name);
    }
    catch (WaitHandleCannotBeOpenedException)
    {
        return new EventWaitHandle(false, EventResetMode.AutoReset, name);
    }
}


...


foreach(var waitHandle in waitHandles)
{
    waitHandle.Set();
}

如果您想知道在执行Reset()之前如何等待所有等待者收到信号,其中等待者是同一进程中的不同线程,那么请从类的MSDN页面查看此示例

使用系统;
使用系统线程;
公开课范例
{
//用于演示差异的EventWaitHandle
//在自动重置和手动重置同步事件之间。
//
私有静态事件WaitHandle ewh;
//一个计数器,用于确保所有线程都已启动并
//在释放任何之前被阻止。长字符用于显示
//使用64位联锁方法。
//
私有静态长线程计数=0;
//允许主线程阻塞的自动重置事件
//直到退出线程减少计数。
//
私有静态EventWaitHandle clearCount=
新的EventWaitHandle(false,EventResetMode.AutoReset);
[MTA线程]
公共静态void Main()
{
//创建自动重置EventWaitHandle。
//
ewh=新的EventWaitHandle(false,EventResetMode.AutoReset);
//创建并启动五个编号的线程。使用
//ParameterizedThreadStart委托,因此线程
//数字可以作为参数传递给Start
//方法。
对于(int i=0;i 0)
{
WriteLine(“按ENTER键释放等待的线程”);
Console.ReadLine();
//SignalAndWait向EventWaitHandle发出信号,它
//重置前只释放一个线程,
//因为它是用自动重置模式创建的。
//SignalAndWait然后阻塞clearCount,以
//允许发出信号的线程减少计数
//在再次循环之前。
//
WaitHandle.SignalAndWait(ewh,clearCount);
}
Console.WriteLine();
//创建ManualReset EventWaitHandle。
//
ewh=新的EventWaitHandle(错误,EventResetMode.ManualReset);
//创建并启动另外五个编号的线程。
//

对于(int i=0;ii)我解决了问题。我使用内存映射文件存储事件等待句柄名称列表。超时无法稳定工作。当前解决方案在2年内投入生产

要想拥有类似p2p的IPC桌面事件,我使用了下一个收据:

  • 1共享互斥
  • 每个进程(事件参与者)1个唯一的服务员和1个唯一的响应者事件等待句柄
  • 1个内存映射文件,用于存储等待的参与者注册表(可使用real registry)
  • 1个用于交换事件数据的内存映射文件

使用EventResetMode.Manual并将EventWaitHandle存储在静态中。使用者应从此静态中读取句柄。无论何时您将要调用Set(),首先创建一个新的EventWaitHandle并将其存储在该静态文件中。下一次消费者想要一个句柄时,他将得到一个新的句柄,这一点很清楚。

你是说“线程”而不是“进程”,那么这种方法将不适用于你……你不能使用
EventWaitHandle
在两个不同的进程之间进行同步我可以有几个ral进程作为侦听器。
_eventWaitHandle.WaitOne();
Console.WriteLine("Hello");
    internal static EventWaitHandle OpenExistingOrCreateEventWaitHandle(string name)
    {
        try
        {
            return EventWaitHandle.OpenExisting(name);
        }
        catch (WaitHandleCannotBeOpenedException)
        {
            return new EventWaitHandle(false, EventResetMode.ManualReset, name);
        }
    }
_eventWaitHandle.Set();
Thread.Sleep(10);
_eventWaitHandle.Reset();
foreach(var process in _myProcesses)
{
    waitHandles.Add(OpenExistingOrCreateEventWaitHandle(process.SharedWaitHandleName);
}

...

internal static EventWaitHandle OpenExistingOrCreateEventWaitHandle(string name)
{
    try
    {
        return EventWaitHandle.OpenExisting(name);
    }
    catch (WaitHandleCannotBeOpenedException)
    {
        return new EventWaitHandle(false, EventResetMode.AutoReset, name);
    }
}


...


foreach(var waitHandle in waitHandles)
{
    waitHandle.Set();
}
using System;
using System.Threading;

public class Example
{
    // The EventWaitHandle used to demonstrate the difference
    // between AutoReset and ManualReset synchronization events.
    //
    private static EventWaitHandle ewh;

    // A counter to make sure all threads are started and
    // blocked before any are released. A Long is used to show
    // the use of the 64-bit Interlocked methods.
    //
    private static long threadCount = 0;

    // An AutoReset event that allows the main thread to block
    // until an exiting thread has decremented the count.
    //
    private static EventWaitHandle clearCount = 
        new EventWaitHandle(false, EventResetMode.AutoReset);

    [MTAThread]
    public static void Main()
    {
        // Create an AutoReset EventWaitHandle.
        //
        ewh = new EventWaitHandle(false, EventResetMode.AutoReset);

        // Create and start five numbered threads. Use the
        // ParameterizedThreadStart delegate, so the thread
        // number can be passed as an argument to the Start 
        // method.
        for (int i = 0; i <= 4; i++)
        {
            Thread t = new Thread(
                new ParameterizedThreadStart(ThreadProc)
            );
            t.Start(i);
        }

        // Wait until all the threads have started and blocked.
        // When multiple threads use a 64-bit value on a 32-bit
        // system, you must access the value through the
        // Interlocked class to guarantee thread safety.
        //
        while (Interlocked.Read(ref threadCount) < 5)
        {
            Thread.Sleep(500);
        }

        // Release one thread each time the user presses ENTER,
        // until all threads have been released.
        //
        while (Interlocked.Read(ref threadCount) > 0)
        {
            Console.WriteLine("Press ENTER to release a waiting thread.");
            Console.ReadLine();

            // SignalAndWait signals the EventWaitHandle, which
            // releases exactly one thread before resetting, 
            // because it was created with AutoReset mode. 
            // SignalAndWait then blocks on clearCount, to 
            // allow the signaled thread to decrement the count
            // before looping again.
            //
            WaitHandle.SignalAndWait(ewh, clearCount);
        }
        Console.WriteLine();

        // Create a ManualReset EventWaitHandle.
        //
        ewh = new EventWaitHandle(false, EventResetMode.ManualReset);

        // Create and start five more numbered threads.
        //
        for(int i=0; i<=4; i++)
        {
            Thread t = new Thread(
                new ParameterizedThreadStart(ThreadProc)
            );
            t.Start(i);
        }

        // Wait until all the threads have started and blocked.
        //
        while (Interlocked.Read(ref threadCount) < 5)
        {
            Thread.Sleep(500);
        }

        // Because the EventWaitHandle was created with
        // ManualReset mode, signaling it releases all the
        // waiting threads.
        //
        Console.WriteLine("Press ENTER to release the waiting threads.");
        Console.ReadLine();
        ewh.Set();

    }

    public static void ThreadProc(object data)
    {
        int index = (int) data;

        Console.WriteLine("Thread {0} blocks.", data);
        // Increment the count of blocked threads.
        Interlocked.Increment(ref threadCount);

        // Wait on the EventWaitHandle.
        ewh.WaitOne();

        Console.WriteLine("Thread {0} exits.", data);
        // Decrement the count of blocked threads.
        Interlocked.Decrement(ref threadCount);

        // After signaling ewh, the main thread blocks on
        // clearCount until the signaled thread has 
        // decremented the count. Signal it now.
        //
        clearCount.Set();
    }
}