These advanced design patterns show how one thread can wait to be signalled from another thread, and to time out after a specified period.
For a thread to signal to a waiting thread that there is work to do:
// required for AutoResetEvent class
using System.Threading;
// initialize an event object
private AutoResetEvent dataReadyEvent = new AutoResetEvent( false );
private byte[] dataToProcess;
private void ReceiveData( byte[] data )
{
// copy the received data
dataToProcess = data.CopyTo( dataToProcess );
// signal to the waiting thread that there is data to process
dataReadyEvent.Set();
}
private void ProcessData()
{
// wait indefinitely for the event object to become signalled
while( dataReadyEvent.WaitOne( System.Threading.Timeout.Infinite, false ) )
{
if( dataToProcess.Length == 0 )
{
// there is no data to process; exit this thread
this.Logger.Debug( "No data to process; exiting thread." );
return;
}
else
{
// display the data and continue waiting
for( int i = 0; i < dataToProcess.Length; i++ )
{
this.Logger.Debug( String.Format( "byte {0} = {1:X2}", i, dataToProcess[i] ) );
}
}
}
}
This design pattern:
declares an AutoResetEvent object dataReadyEvent, and set its initial state to non-signaled,
declares a private byte array dataToProcess,
the ReceiveData method accepts a byte array parameter data,
the method copies the contents of data to the dataToProcess arrayand sets the dataReadyEvent object to signaled,
the ProcessData method waits indefinitely for the dataReadyEvent object to become signaled,
when it is signaled, the method checks whether the dataToProcess array contains any data, if not the method exits, terminating the thread,
if there is data to process, the method displays the array contents,
thereafter it re-enters the while loop, and continues to wait for the dataReadyEvent object.
A thread that periodically performs a task, but can be signalled to terminate from another thread:
// required for AutoResetEvent class
using System.Threading;
// initialize an event object
private AutoResetEvent quitEvent = new AutoResetEvent( false );
private void SendHeartbeat()
{
// wait 10 seconds for the event object to become signalled
while( quitEvent.WaitOne( 10000, false ) == false )
{
// the wait timed out: send the heartbeat message, and continue waiting
this.Logger.Debug( "Sending heartbeat" );
}
// the event was signaled; exit this thread
this.Logger.Debug( "Signaled to quit; exiting thread." );
}
private void StopHeartbeat()
{
// signal to the heartbeat thread to terminate
quitEvent.Set();
}
This design pattern:
declares an AutoResetEvent object quitEvent, and set its initial state to non-signaled,
the SendHeartbeat method waits for 10,000ms (10 seconds) for the quitEvent object to become signaled,
if the WaitOne operation times out (i.e. returns false) the method displays a heartbeat message, and re-enters the while loop,
if the quitEvent is signaled, the while loop breaks and the method displays a quit message; the method exits, terminating the thread,
the StopHeartbeat method can be called from another thread, and sets the quitEvent object to signaled.