我在一个进程中执行:
_eventWaitHandle.Set();
_eventWaitHandle.Reset();
在另一个进程中:
_eventWaitHandle.WaitOne();
Console.WriteLine("Hello");
但永远不会得到通知(没有控制台输出)。 它似乎是异步设置。
我怎能等到所有服务员都在发出重置()之前发出信号?
我创建了等待句柄( NAMED进程间等待句柄):
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();
第二种可能 - 为每个进程提供许多句柄。但是此代码应该适用于任何Office应用程序加载项或独立应用程序。因此,应该如何生成名称和发现。
第三 - 使用WCF p2p(netPeerTcpBinding)或命名管道与UdpDiscoveryEndpoint-但这些使用“IP”,因此在部署到最终用户时可能会遇到一些安全问题?
答案 0 :(得分:2)
是的,Set()
函数会立即退出,因此调用Set()
和Reset()
时,基本上什么都不做,或者随机执行某些操作。您可以通过在WaitOne()
。
答案 1 :(得分: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();
}
答案 2 :(得分:0)
如果您想知道如何等待所有服务员在执行Reset()之前发出信号,其中服务员是同一进程中的不同线程,那么请查看EventWaitHandle的MSDN页面中的此示例类
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();
}
}
答案 3 :(得分:0)
我解决了问题。我使用内存映射文件来存储事件等待句柄名称列表。超时无法稳定工作。目前的解决方案在2年内投入生产。
要像我在下一张收据中使用的IPC桌面事件那样p2p:
答案 4 :(得分:0)
使用EventResetMode.Manual并将EventWaitHandle存储在静态中。消费者应该从这个静态读取句柄。每当您要调用Set()时,首先创建一个新的EventWaitHandle并将其存储在该静态中。下一次消费者想要处理时,他会得到新的,这很清楚。