2011-08-31 41 views
1

我在一個過程做EventWaitHandle.Set(後發出的所有進程:一直等到)

_eventWaitHandle.Set(); 
_eventWaitHandle.Reset(); 

在另一個過程

_eventWaitHandle.WaitOne(); 
Console.WriteLine("Hello"); 

但從來沒有得到通知(無控制檯輸出)。 它似乎設置爲異步。

如何等待,直到所有服務員在進行Reset()之前發出信號?

我創建等待句柄(NAMED進程間等待處理):

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

UPDATE

現在我有一個 「解決方案」

_eventWaitHandle.Set(); 
Thread.Sleep(10); 
_eventWaitHandle.Reset(); 

第二個可能的 - 每個過程都有多個手柄。但是這個代碼應該可以在任何辦公應用程序加載項或獨立應用程序中運行。所以應該生成一些名稱和發現的名稱。

第三 - 使用WCF p2p(netPeerTcpBinding)或帶有UdpDiscoveryEndpoint的命名管道 - 但這些使用「IP」,因此在部署到最終用戶時可能存在一些安全問題?

+2

你的意思是'線程'而不是'進程' – Rishabh

+0

我的意思是其他進程。 –

+0

然後這種方法不適用於你...你不能使用一個'EventWaitHandle'在兩個不同的進程之間同步 – Rishabh

回答

0

我解決了問題。我使用內存映射文件來存儲事件等待句柄名稱的列表。超時未能穩定工作。目前的解決方案在2年內投入生產。

有像IPC桌面事件的p2p我用接下來的收據:

  • 1共享互斥
  • 1名獨特的服務員和1個獨特的響應事件每個進程等待句柄(三項賽的參與者)
  • 1內存映射文件來存儲參與者等待的註冊表(可以使用真實的註冊表)
  • 1個用於事件數據交換的存儲器映射文件
2

是的Set()功能退出imemdiately,所以有Set()Reset()調用,因爲你基本上什麼都不做,或隨意做一些事情。您可以通過在WaitOne()之後重置偵聽線程上的事件來解決問題。

1

您可以將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(); 
} 
+0

我可以有幾個進程作爲監聽器。 –

0

如果你想知道如何要等到所有的服務員在做復位(),其中侍應生在同一進程不同線程之前發出信號,然後看看這個例子從EventWaitHandle的MSDN頁class

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(); 
    } 
} 
0

使用EventResetMode.Manual並將您的EventWaitHandle存儲在靜態中。消費者應該閱讀這個靜態的句柄。每當你要調用Set()時,首先創建一個新的EventWaitHandle並將其存儲在該靜態中。消費者下一次想要處理時,他會得到新的,這很清楚。