Blocking and waiting for an event

后端 未结 5 1627
不知归路
不知归路 2020-12-15 03:45

It sometimes want to block my thread while waiting for a event to occur.

I usually do it something like this:

private AutoResetEvent _autoResetEvent          


        
5条回答
  •  北海茫月
    2020-12-15 04:23

    I've rushed together a working sample in LinqPad using reflection, getting a reference to the EventInfo object with a string (be careful as you loose compile time checking). The obvious issue is that there is no guarentee an event will ever be fired, or that the event your expecting may be fired before the EventWaiter class is ready to start blocking so I'm not sure I'd sleep comfy if I put this in a production app.

    void Main()
    {
        Console.WriteLine( "main thread started" );
    
        var workerClass = new WorkerClassWithEvent();
        workerClass.PerformWork();
    
        var waiter = new EventWaiter( workerClass, "WorkCompletedEvent" );
        waiter.WaitForEvent( TimeSpan.FromSeconds( 10 ) );
    
        Console.WriteLine( "main thread continues after waiting" );
    }
    
    public class WorkerClassWithEvent
    {
        public void PerformWork()
        {
            var worker = new BackgroundWorker();
            worker.DoWork += ( s, e ) =>
            {
                Console.WriteLine( "threaded work started" );
                Thread.Sleep( 1000 ); // <= the work
                Console.WriteLine( "threaded work complete" );
            };
            worker.RunWorkerCompleted += ( s, e ) =>
            {
                FireWorkCompletedEvent();
                Console.WriteLine( "work complete event fired" );
            };
    
            worker.RunWorkerAsync();
        }
    
        public event Action WorkCompletedEvent;
        private void FireWorkCompletedEvent()
        {
            if ( WorkCompletedEvent != null ) WorkCompletedEvent();
        }
    }
    
    public class EventWaiter
    {
        private AutoResetEvent _autoResetEvent = new AutoResetEvent( false );
        private EventInfo _event               = null;
        private object _eventContainer         = null;
    
        public EventWaiter( object eventContainer, string eventName )
        {
            _eventContainer = eventContainer;
            _event = eventContainer.GetType().GetEvent( eventName );
        }
    
        public void WaitForEvent( TimeSpan timeout )
        {
            _event.AddEventHandler( _eventContainer, (Action)delegate { _autoResetEvent.Set(); } );
            _autoResetEvent.WaitOne( timeout );
        }
    }
    

    Output

    // main thread started
    // threaded work started
    // threaded work complete
    // work complete event fired
    // main thread continues after waiting
    

提交回复
热议问题