|
using System;
using System.Runtime.Remoting.Proxies;
using System.Threading;
using System.Runtime.Remoting;
using System.Security.Permissions;
namespace ThreadBound
{
/// <summary>
/// This attribute binds a class to a thread. Every method call will be executed within the same thread. Method
/// calls from other threads will be transported to the classes thread.
/// </summary>
/// <remarks>
/// If the attribute is used with the ThreadBinding CurrentContext the class must be instantiated from within
/// a SynchronisationContext. Normally this is WPF- or Forms-GUI-threads. If the current context is null an
/// exception will be thrown.
/// </remarks>
[AttributeUsage(AttributeTargets.Class)]
[SecurityPermissionAttribute(SecurityAction.Demand, Flags = SecurityPermissionFlag.Infrastructure)]
public class ThreadBoundAttribute : ProxyAttribute
{
/// <summary>
/// Enummeration of contexts that can be used to bind a class instance to:
/// <list type="bullet">
/// <item>
/// <term>CurrentContext</term>
/// <description>Use the current context. This type is only valid if the class gets instanciated within a WPF or WinForms GUI context.</description>
/// </item>
/// <item>
/// <term>WorkerContext</term>
/// <description>Creates a dedicated worker thread for each instance of the class.</description>
/// </item>
/// <item>
/// <term>PoolContext</term>
/// <description>Uses the thread pool to execute the methods of the class. The different methods may be executed on different thread pool threads.</description>
/// </item>
/// </list>
/// </summary>
public enum ThreadBinding {CurrentContext, WorkerContext, PoolContext};
/// <summary>
/// The thread binding set via the first parameter of the attribute.
/// </summary>
private ThreadBinding DesiredBindingType;
/// <summary>
/// c'tor: Defaulting to binding the current instance to the current context
/// </summary>
public ThreadBoundAttribute() :
this(ThreadBinding.CurrentContext)
{
//-- The default is to use an existing context.
}
/// <summary>
/// c'tor: Binds all instances of a class marked with this attribute to the selected context.
/// </summary>
/// <param name="bindingType">A binding type describe within the <see cref="ThreadBoundAttribute.ThreadBinding"/>ThreadBinding</see> enumeration.</param>
public ThreadBoundAttribute(ThreadBinding bindingType) :
base()
{
DesiredBindingType = bindingType;
}
/// <summary>
/// This method is called by the framework if a class derived from ContextBoundObject and taged with a proxy
/// attribute is instantiated.
/// </summary>
/// <param name="serverType">Type the framework is trying to create an instance of.</param>
/// <returns>Returns the new instance casted to a MarshalByRefObject reference.</returns>
public override MarshalByRefObject CreateInstance(Type serverType)
{
SynchronizationContext ExecContext=null;
if (!serverType.IsContextful)
throw new ThreadBoundException("Type must be derived from ContextBoundObject or ThreadBoundObject.");
//-- Instanciate a cleass that implements the SynchronisationContext to use
switch (DesiredBindingType)
{
case ThreadBinding.CurrentContext:
ExecContext = SynchronizationContext.Current;
if (ExecContext == null)
throw new ThreadBoundException("Can't use current context, because there is no current context set.");
break;
case ThreadBinding.WorkerContext:
if (!typeof(IDisposable).IsAssignableFrom(serverType))
throw new ThreadBoundException("Worker instances must im plement IDisposable.");
ExecContext = new WorkerSynchronizationContext(new Worker("ThreadBoundContextWorker"));
break;
case ThreadBinding.PoolContext:
ExecContext = new PoolSynchronizationContext();
break;
}
ThreadBoundProxy newProxy = new ThreadBoundProxy(serverType, ExecContext);
return (MarshalByRefObject)newProxy.GetTransparentProxy();
}
}
}
|
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.