2

EventWaitHandleどちらが呼び出されたかを知る方法はありますか。

2 つの異なるシステム全体のイベント名を持つ 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 アプリケーションまたはデスクトップ アプリケーションからイベントをトリガーしたユーザーを特定する必要があります。Web アプリケーションの場合は SP1 を実行し、Windows アプリケーションの場合は SP2 を実行します。

4

5 に答える 5

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

また、1 つのイベント ハンドルを 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を使用して、複数のイベントハンドルを待機します。1つ以上のイベントが設定されると、待機が戻る原因となったイベントのインデックスが返されます。

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 メソッドを実装する必要があります (WaitOne に対応して拡張するために WaitNew を実装しました)。

作業コードについては、次のコードを参照してください。

//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、揮発性の「Caller」プロパティを追加します。すべてのシグナル送信者は、自分の ID または Ref を渡す必要があります。
Signalled の後、Interlockはプロパティをチェックします。

于 2013-03-06T08:30:51.257 に答える