0

What is the correct way in C# to wait for one of these events, which comes first: an AutoResetEvent is set or another Thread is ended?

To wait for multiple wait handles can be used WaitHandle.WaitAny. But Thread is not WaitHandle.

Example:

class Example
{
    AutoResetEvent _stopEvent = new AutoResetEvent(false);

    public void Start()
    {
        var handles = new WaitHandle[] { _stopEvent, Thread.CurrentThread }; //error: Thread is not WaitHandle
        var t = new Thread(() =>
        {
            //...

            int r = WaitHandle.WaitAny(handles);
            switch(r) {
            case 0: Console.WriteLine("Stop called"); break;
            case 1: Console.WriteLine("thread ended"); break;
            }

            //...
        });
        t.SetApartmentState(ApartmentState.STA);
        t.Start();
    }

    public void Stop()
    {
        _stopEvent.Set();
    }
}

Currently I use this workaround.

class Workaround
{
    AutoResetEvent _stopEvent = new AutoResetEvent(false);

    public void Start()
    {
        var stopEvent = _stopEvent;
        var thread1 = Thread.CurrentThread;
        var t = new Thread(() =>
        {
            //...

            while(!stopEvent.WaitOne(100)) {
                if(thread1.Join(0)) break;
            }

            //...
        });
        t.SetApartmentState(ApartmentState.STA);
        t.Start();
    }

    public void Stop()
    {
        _stopEvent.Set();
    }
}

I am aware about the native API - WaitForMultipleObjects etc, but would like to avoid it.

The code will be in a library; it cannot explicitly set event when the thread is ending.

gindi
  • 9
  • 2
  • Luckily waiting on Thread.CurrentThread makes no sense at all, so it is a problem you don't have to solve. Consider the Task class for more options. – Hans Passant Mar 28 '18 at 12:47
  • In this case waiting for Thread.CurrentThread makes sense. I want to start another thread and let it end when current thread ends. Current thread possibly is not the primary thread. Cannot use the Task class because need single-threaded apartment. – gindi Mar 28 '18 at 13:23
  • That doesn't sound good. A hard requirement for an STA thread is that it must stay running as long as the COM objects it owns are not finalized yet. Failure to observe that requirement causes the finalizer thread to deadlock, very nasty problem to troubleshoot. Only truly safe way to do this is to leave it always running. – Hans Passant Mar 28 '18 at 13:29
  • In this case the started thread does not use COM. It uses a Windows API function SetWinEventHook, therefore the thread must process Windows messages while waiting. .NET functions like WaitOne and Join process messages only in STA thread. – gindi Mar 28 '18 at 13:50

0 Answers0