2

有没有办法知道哪个EventWaitHandle被调用了。

我有两个具有 2 个不同系统范围事件名称的自定义类。

我拥有它们的原因是为了区分要触发的功能。

我现在遇到的问题是如何区分触发了哪个事件?

EventWaitHandle _ew1 = new EventWaitHandle(false, EventResetMode.AutoReset, "Mode1");
EventWaitHandle _ew2 = new EventWaitHandle(false, EventResetMode.AutoReset, "Mode2");

所以如果_ew1.Set()被调用,那么我需要执行Process1.

如果 _ew2.Set() 被调用,那么我需要执行Process2.

更新:添加了更多信息。

主线程是 Windows 服务。由 Web 应用程序和桌面应用程序发出信号。因此,基本上该服务需要确定谁从 Web 应用程序或桌面应用程序触发了事件,如果它是 WebAppliation,则执行 SP1,否则如果它是 Windows 应用程序,则执行 SP2。

4

5 回答 5

2

理念一

WaitHandle.WaitAny静态方法返回信号等待句柄的索引,因此最简单的解决方案是检查该索引。

例子

static class Program
{
    private static Random _random = new Random();
    private static AutoResetEvent[] _eventHandles = new[] {new AutoResetEvent(false), new AutoResetEvent(false)};

    static void Main()
    {
        Thread[] threads = new Thread[10];

        for (int i = 0; i < threads.Length; i++)
        {
            threads[i] = new Thread(Method);
            threads[i].Start();

            var handleIndex = WaitHandle.WaitAny(_eventHandles);
            Console.WriteLine(handleIndex == 0 ? "Process1" : "Process2");
        }
    }

    static void Method()
    {
        if (_random.Next()%2 == 0)
            _eventHandles[0].Set();
        else
            _eventHandles[1].Set();
    }
}

想法 2

您还可以使用一个事件句柄和一个 volatile 字段,该字段将指示满足了哪些条件语句,以便在信号后执行适当的过程。

例子

enum Process
{
    Process1,
    Process2
}

static class Program
{
    private static Random _random = new Random();

    private static AutoResetEvent _eventHandle = new AutoResetEvent(false);
    private static volatile Process _selectedProcess = Process.Process1;

    static void Main()
    {
        Thread[] threads = new Thread[10];

        for (int i = 0; i < threads.Length; i++)
        {
            threads[i] = new Thread(Method);
            threads[i].Start();

            _eventHandle.WaitOne();

            Console.WriteLine(_selectedProcess == Process.Process1 ? "Process1" : "Process2");
        }
    }

    static void Method()
    {
        _selectedProcess = _random.Next()%2 == 0 ? Process.Process1 : Process.Process2;
        _eventHandle.Set();
    }
}

想法 3

如果您无法修改外部组件并且您只有事件句柄,那么您可以尝试为每个选项启动新线程并在那里等待相应的信号以执行适当的操作。

例子

static class Program
{
    private static Random _random = new Random();
    private static AutoResetEvent[] _eventHandles = new[] {new AutoResetEvent(false), new AutoResetEvent(false)};

    static void Main()
    {
        Thread[] processThreads = new Thread[2];

        processThreads[0] = new Thread(Process1);
        processThreads[0].Start();

        processThreads[1] = new Thread(Process2);
        processThreads[1].Start();


        Thread[] threads = new Thread[10];

        for (int i = 0; i < threads.Length; i++)
        {
            threads[i] = new Thread(Method);
            threads[i].Start();
        }
    }

    static void Method()
    {
        if (_random.Next()%2 == 0)
            _eventHandles[0].Set();
        else
            _eventHandles[1].Set();
    }

    static void Process1()
    {
        while (true)
        {
            _eventHandles[0].WaitOne();
            Console.WriteLine("Process1");
        }
    }

    static void Process2()
    {
        while (true)
        {
            _eventHandles[1].WaitOne();
            Console.WriteLine("Process2");
        }
    }
}

想法4

如果进程需要少量时间,可以使用ThreadPool.RegisterWaitForSingleObject 方法

例子

static class Program
{
    private static Random _random = new Random();
    private static AutoResetEvent[] _eventHandles = new[] {new AutoResetEvent(false), new AutoResetEvent(false)};

    static void Main()
    {
        ThreadPool.RegisterWaitForSingleObject(_eventHandles[0], Process1, null, Timeout.Infinite, false);
        ThreadPool.RegisterWaitForSingleObject(_eventHandles[1], Process2, null, Timeout.Infinite, false);


        Thread[] threads = new Thread[10];

        for (int i = 0; i < threads.Length; i++)
        {
            threads[i] = new Thread(Method);
            threads[i].Start();
        }
    }

    static void Method()
    {
        if (_random.Next()%2 == 0)
            _eventHandles[0].Set();
        else
            _eventHandles[1].Set();
    }

    static void Process1(object state, bool timedOut)
    {
        Console.WriteLine("Process1");
    }

    static void Process2(object state, bool timedOut)
    {
        Console.WriteLine("Process2");
    }
}
于 2013-03-06T08:00:34.243 回答
1

使用WaitHandle.WaitAny等待多个事件句柄。当设置一个或多个事件时,它将返回导致等待返回的事件的索引。

EventWaitHandle _ew1 = new EventWaitHandle(false, EventResetMode.AutoReset, "Mode1");
EventWaitHandle _ew2 = new EventWaitHandle(false, EventResetMode.AutoReset, "Mode2");

WaitHandle[] handles={_ew1, _ew2};

int index=WaitHandle.WaitAny(handles)

if(index==0)
{
  // mode 1
}
else if(index==1)
{
  // mode 2
}
于 2013-03-06T08:42:03.020 回答
1

我可以建议的一个想法是创建自己的 EventWaitHandler,它可以重用处理程序的名称,稍后这个名称应该从 Wait 方法返回并作为调用者的标识符

为此,您必须实现自己的 Wait 方法(我实现了 WaitNew 来满足和扩展 WaitOne)

有关工作代码,请参见以下代码:

//Client application environments
public class WindowsApplication
{
    public void ExecuteWindowsService()
    {
        var ws = new WindowsService();
        var _eventHandle = new MyEventWaitHandler(false, EventResetMode.AutoReset, "WindowsApplicationMode");
        ws.Execute(_eventHandle);
        _eventHandle.Set();
    }

}
public class WebApplication
{
    public void ExecuteWebService()
    {
        var ws = new WindowsService();
        var _eventHandle = new MyEventWaitHandler(false, EventResetMode.AutoReset, "WebApplicationMode");
        ws.Execute(_eventHandle);
        _eventHandle.Set();
    }
}



//Windows Service Environment
public class MyEventWaitHandler : EventWaitHandle
{
    public MyEventWaitHandler(bool initialState, EventResetMode mode, string name)
        : base(initialState, mode, name)
    {
        this.EventHandlerName = name;
    }

    //it should not be set to empty string from external
    public string EventHandlerName;

    public string WaitNew()
    {
        if (base.WaitOne())
            return EventHandlerName;
        else return String.Empty;
    }
}

public class WindowsService
{
    public void Execute(MyEventWaitHandler _eventHandle)
    {
        Thread[] threads = new Thread[10];
        for (int i = 0; i < threads.Length; i++)
        {
            threads[i] = new Thread(Method);
            threads[i].Start();

            string name = _eventHandle.WaitNew();

            if (name == "WindowsApplicationMode")
            {
                //Execute case for first process
            }
            else if (name == "WebApplicationMode")
            {
                //Execute case for second process
            }
        }
    }

    static void Method()
    {
        //Some Task
    }
}

让我知道我是否理解您的要求正确?

于 2013-03-06T08:52:19.627 回答
0

继承自EventWaitHandle,添加一个易变的“调用者”属性。每个信号员都必须通过他的 ID,或 Ref。
发出信号后,联锁检查属性。

于 2013-03-06T08:30:51.257 回答
0

这个怎么样?

bool signaled = eventWaitHandle.WaitOne(TimeSpan.Zero);
于 2014-07-04T02:46:28.103 回答