|
using System;
using System.Threading;
namespace ThreadBound
{
/// <summary>
/// Base class for all (synchronous and asynchronous) WorkQueueItems.
/// Each WorkQueueItem represents an action to execute within an other thread.
/// </summary>
internal abstract class WorkQueueItem
{
/// <summary>
/// Reference to a delegate that will be called if the QueueItem is invoked.
/// </summary>
private SendOrPostCallback Callback;
/// <summary>
/// A reference that should be passed to the state-parameter of the Invoke method call.
/// </summary>
private Object State;
/// <summary>
/// C'tor
/// </summary>
/// <param name="callback">Reference to a delegate that will be called if the QueueItem is invoked.</param>
/// <param name="state">A reference that should be passed to the state-parameter of the Invoke method call.</param>
public WorkQueueItem(SendOrPostCallback callback, Object state)
{
Callback = callback;
State = state;
}
/// <summary>
/// Invokes the callback passed to the c'tor with the set state.
/// </summary>
public virtual void Invoke()
{
Callback.Invoke(State);
}
}
/// <summary>
/// WorkQueueItem for synchronous method calls
/// </summary>
internal class SyncWorkQueueItem :
WorkQueueItem
{
/// <summary>
/// A thread static done event. Because every thread can only execute one function at
/// a time. One global done event per thread is sufficient.
/// </summary>
[ThreadStatic]
private static AutoResetEvent GlobalDoneEvent;
/// <summary>
/// Done event for this QueueItem. Will be set to the global Done event.
/// </summary>
private AutoResetEvent DoneEvent;
/// <summary>
/// If an exception is raised within Invoke the exception is stored within
/// this variable. It can be rethrown by using RethrowException.
/// </summary>
private volatile Exception LastException;
/// <summary>
/// C'tor
/// </summary>
/// <param name="callback">Reference to a delegate that will be called if the QueueItem is invoked.</param>
/// <param name="state">A reference that should be passed to the state-parameter of the Invoke method call.</param>
public SyncWorkQueueItem(SendOrPostCallback callback, Object state) :
base(callback, state)
{
//-- Because every thread waits until the current synchronous call is done,
// one done event per thread is enough. It is created and cached.
// This simple locking is sufficient because there is only one thread
// using this "singleton".
if (GlobalDoneEvent == null)
GlobalDoneEvent = new AutoResetEvent(false);
DoneEvent = GlobalDoneEvent;
}
/// <summary>
/// Waits for the current invokation to complete.
/// </summary>
public void Join()
{
DoneEvent.WaitOne();
}
/// <summary>
/// Invokes the method set within the c'tor.
/// </summary>
/// <seealso cref="WorkQueueItem.WorkQueueItem"/>
public override void Invoke()
{
try
{
base.Invoke();
}
catch (Exception allExceptions)
{
LastException = allExceptions;
}
//-- Wenn ein Done-Event mit diesem Eintrag verknüpft ist, dieses jetzt setzen
DoneEvent.Set();
}
/// <summary>
/// Allows the usage of SyncWorkQueueItem within a PoolSynchronizationContext wich requres a parameter.
/// </summary>
/// <param name="state">Dummy-parameter to use this class with WaitCallback.</param>
public void Invoke(Object state)
{
Invoke();
}
/// <summary>
/// If an exception occured within Invoke this methods rethrows the exception. If no exception
/// occured the method will do nothing.
/// </summary>
public void RethrowException()
{
if (LastException != null)
throw LastException;
}
};
/// <summary>
/// WorkQueueItem for asynchronous calls.
/// </summary>
/// <remarks>Implements nothing more than the base class. Only a thin wraper because asynchronous calls do not need any synchronization.</remarks>
internal class AsyncWorkQueueItem :
WorkQueueItem
{
/// <summary>
/// C'tor
/// </summary>
/// <param name="callback">Reference to a delegate that will be called if the QueueItem is invoked.</param>
/// <param name="state">A reference that should be passed to the state-parameter of the Invoke method call.</param>
public AsyncWorkQueueItem(SendOrPostCallback callback, Object state) :
base(callback, state)
{
}
};
}
|
By viewing downloads associated with this article you agree to the Terms of Service and the article's licence.
If a file you wish to view isn't highlighted, and is a text file (not binary), please
let us know and we'll add colourisation support for it.
This member has not yet provided a Biography. Assume it's interesting and varied, and probably something to do with programming.