如何知道是否调用了EventWaitHandle.Set

时间:2013-03-06 07:53:15

标签: c# multithreading event-wait-handle

有没有办法知道调用了哪个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。

5 个答案:

答案 0 :(得分:2)

想法1

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

您还可以使用一个事件句柄以及一个易失性字段,该字段将指示已经满足的条件语句,以便在信号之后执行适当的处​​理。

实施例

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 Method

实施例

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");
    }
}

答案 1 :(得分: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
}

答案 2 :(得分:1)

我可以建议的IDEA是创建自己的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
    }
}

如果我理解您的要求是否正确,请告诉我?

答案 3 :(得分:0)

继承自EventWaitHandle,添加易变的“来电者”属性。每个信号员必须通过他的身份证或参考号 发信号后,联锁检查属性。

答案 4 :(得分:0)

这个怎么样?

bool signaled = eventWaitHandle.WaitOne(TimeSpan.Zero);