|
using System.Runtime.Remoting.Messaging;
using System.Runtime.Serialization.Formatters.Binary;
using System.IO;
using System.Threading;
namespace ThreadBound
{
/// <summary>
/// Describes the various call states of a remote method.
/// <list type="bullet">
/// <item>
/// <term>Waiting</term>
/// <description>The message is waiting to be executed.</description>
/// </item>
/// <item>
/// <term>Running</term>
/// <description>The message is currently executing.</description>
/// </item>
/// <item>
/// <term>Done</term>
/// <description>The message was executed.</description>
/// </item>
/// <item>
/// <term>Cancel</term>
/// <description>The execution of this message was canceled.</description>
/// </item>
/// </list>
/// </summary>
public enum CallStates { Waiting = 0, Running = 1, Done = 2, Canceled = 10 };
/// <summary>
/// This interface must be implemented by every class representing a method call within the
/// queue of the SynchronisationContext. This interface triggers the execution of the method
/// call on the remote side.
/// </summary>
internal interface IRemoteMethod
{
/// <summary>
/// Returns the IMethodCallMessage interface describing the method call represented by this IRemoteMethod instance.
/// </summary>
IMethodCallMessage CallMessage { get; }
/// <summary>
/// Sets the return message of the method call.
/// </summary>
/// <param name="returnMessage"></param>
void SetReturnMessage(IMethodReturnMessage returnMessage);
/// <summary>
/// Sets the state of the method call. This enables the retrieval of the execution state of asynchronous method calls via the IAsyncCallState interface.
/// </summary>
/// <param name="newState">The new call state to set.</param>
/// <seealso cref="SyncRemoteMethod.SetState(CallStates newState)"/>
/// <seealso cref="AsyncRemoteMethod.SetState(CallStates newState)"/>
/// <returns>Returns true if the state transition was valid.</returns>
bool SetState(CallStates newState);
/// <summary>
/// Checks if the method call represented by the instace of the object implementing this interface was canceled.
/// </summary>
/// <returns>Returns true if the method call was canceld or false otherwise.</returns>
bool WasCanceled();
}
/// <summary>
/// Transports all parameters for a synchronous method call to the remote side.
/// </summary>
internal class SyncRemoteMethod :
IRemoteMethod
{
private IMethodCallMessage InternalCallMessage;
private IMethodReturnMessage InternalReturnMessage;
/// <summary>
/// c'tor: Constructing a SyncRemoteMethod from an IMethodCallMessage interface.
/// </summary>
/// <param name="callMessage">IMethodCallMessage interface describing the method to call on the remote side.</param>
public SyncRemoteMethod(IMethodCallMessage callMessage)
{
InternalCallMessage = callMessage;
}
/// <summary>
/// Returns the IMethodCallMessage interface describing the method call represented by this IRemoteMethod instance.
/// </summary>
/// <seealso cref="IRemoteMethod.CallMessage"/>
public IMethodCallMessage CallMessage
{
get { return InternalCallMessage; }
}
/// <summary>
/// The return Message of the method call.
/// </summary>
/// <seealso cref="SyncRemoteMethod.SetReturnMessage(IMethodReturnMessage returnMessage)"/>
public IMethodReturnMessage ReturnMessage
{
get { return InternalReturnMessage; }
}
/// <summary>
/// Saves the return message of the synchronous method call. The Return message can be retrieved by the ReturnMessage method of this class.
/// </summary>
/// <seealso cref="IRemoteMethod.SetReturnMessage(IMethodReturnMessage returnMessage)"/>
/// <seealso cref="SyncRemoteMethod.ReturnMessage"/>
/// <param name="returnMessage">The IMethodReturnMessage interface containing the result of the method call.</param>
public void SetReturnMessage(IMethodReturnMessage returnMessage)
{
InternalReturnMessage = returnMessage;
}
/// <summary>
/// Sets the new state of this method call.
/// </summary>
/// <seealso cref="IRemoteMethod.SetState(CallStates newState)"/>
/// <param name="newState">The new call state to set.</param>
/// <returns>Returns always true because setting the state on a synchronous method call is not supported.</returns>
public bool SetState(CallStates newState)
{
return true;
}
/// <summary>
/// Checks if the remote method was cancled.
/// </summary>
/// <seealso cref="IRemoteMethod.WasCanceled()"/>
/// <returns>Always returns false because a synchronous method call can not be canceled.</returns>
public bool WasCanceled()
{
return false;
}
}
/// <summary>
/// Transports all parameters for an asynchronous method call to the remote side.
/// </summary>
internal class AsyncRemoteMethod :
IRemoteMethod,
IAsyncCallState
{
/// <summary>
/// Saves the current call state of the method call represented by this AsyncRemoteMethod instance
/// </summary>
private CallStates CurrentCallState;
/// <summary>
/// Object used for locking the CurrentCallState variable for threadsafe access.
/// </summary>
private object CallStateLock = new object();
/// <summary>
/// The IMethodCallMessage interface of the stored method call. This interface is implemented by the used MethodCallMessageWrapper instance.
/// </summary>
private IMethodCallMessage StoredCallMessage;
/// <summary>
/// c'tor: Constructs an AsyncRemoteMethod instance from a IMethodCallMessage interface. The contents of the IMethodCallInterface will be wrapped by a
/// MethodCallMessageWrapper instance.
/// </summary>
/// <param name="callMessage">IMethodCallMessage interface describing the method to call on the other thread.</param>
public AsyncRemoteMethod(IMethodCallMessage callMessage)
{
CurrentCallState = CallStates.Waiting;
//-- Using MethodCallMessageWrapper to wrap all Parameters up and ensure they are not freed until the call
// on the remote sinde has completed. This is a little unofficial - but better than doing it manually.
StoredCallMessage = new MethodCallMessageWrapper(callMessage);
}
/// <summary>
/// Returns the IMethodCallMessage interface describing the method call represented by this IRemoteMethod instance.
/// </summary>
/// <seealso cref="IRemoteMethod.CallMessage"/>
public IMethodCallMessage CallMessage
{
get
{
return StoredCallMessage;
}
}
/// <summary>
/// Sets the return message of the asynchronous method call. The parameter will simply be ignored because asynchronous calls can't return values.
/// </summary>
/// <seealso cref="IRemoteMethod.SetReturnMessage(IMethodReturnMessage returnMessage)"/>
/// <seealso cref="SyncRemoteMethod.ReturnMessage"/>
/// <param name="returnMessage">The IMethodReturnMessage interface containing the result of the method call.</param>
public void SetReturnMessage(IMethodReturnMessage returnMessage)
{
}
/// <summary>
/// Sets the state of the method call. This enables the retrieval of the execution state of asynchronous method calls via the IAsyncCallState interface.
/// </summary>
/// <param name="newState">The new call state to set.</param>
/// <seealso cref="IRemoteMethod.SetState(CallStates newState)"/>
/// <returns>Returns true if the state transition was valid. A state transition is only valid of the current state is less than the new state. See CallStates enumeration for details.</returns>
public bool SetState(CallStates newState)
{
bool bValidTransition = true;
lock (CallStateLock)
{
if (CurrentCallState < newState)
CurrentCallState = newState;
else
bValidTransition = false;
}
return bValidTransition;
}
/// <summary>
/// Returns the current state of the call.
/// <list type="bullet">
/// <item>
/// <term>Waiting</term>
/// <description>The asynchronous call is waiting to be executed.</description>
/// </item>
/// <item>
/// <term>Running</term>
/// <description>The asynchronous call is currently executed.</description>
/// </item>
/// <item>
/// <term>Done</term>
/// <description>The asynchronous call was executed.</description>
/// </item>
/// <item>
/// <term>Cancel</term>
/// <description>The execution of this call was canceled.</description>
/// </item>
/// </list>
/// </summary>
public CallStates CallState
{
get
{
CallStates callState;
lock (CallStateLock)
callState = CurrentCallState;
return callState;
}
}
/// <summary>
/// Checks if the remote method was cancled.
/// </summary>
/// <seealso cref="IRemoteMethod.WasCanceled()"/>
/// <returns>Returns true if the execution of this method call was canceled by a call to <see cref="IAsyncCallState.Cancel()">IAsyncCallState.Cancel().</see></returns>
public bool WasCanceled()
{
return (CallState == CallStates.Canceled);
}
/// <summary>
/// Cancels the execution of this method. If the method is already executing, the thread will be notified about
/// the cancelation. If not, the call state will be set to canceled so the method will never be executed.
/// </summary>
public void Cancel()
{
SetState(CallStates.Canceled);
}
}
}
|
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.