Skip to content

Instantly share code, notes, and snippets.

Embed
What would you like to do?
ApartmentAspect for PostSharp.
namespace ArkaneSystems.Arkane.Aspects
{
/// <summary>
/// An aspect to execute a function on a thread in the given COM apartment state.
/// </summary>
[Serializable]
public sealed class ApartmentAspect : MethodInterceptionAspect
{
private readonly ApartmentState desiredState;
private Exception returnException;
/// <summary>
/// An aspect to execute a function on a thread in the given COM apartment state.
/// </summary>
/// <param name="state">The desired COM apartment state (default STA).</param>
public ApartmentAspect (ApartmentState state = ApartmentState.STA)
{
this.desiredState = state;
}
/// <summary>
/// Method invoked <i>instead</i> of the method to which the aspect has been applied.
/// </summary>
/// <param name="args">Advice arguments.</param>
public override void OnInvoke (MethodInterceptionArgs args)
{
// Obtain current thread's apartment state.
ApartmentState currentState = Thread.CurrentThread.GetApartmentState ();
if (currentState == this.desiredState)
{
// If the current state is the desired state, just proceed.
args.Proceed ();
}
else
{
this.returnException = null;
// Spawn new thread to run args.Proceed, putting it in the desired apartment state.
var aptThread = new Thread (() => this.ProceedOnOtherThread (args));
aptThread.SetApartmentState (this.desiredState);
// Run it and block until it is complete.
aptThread.Start ();
aptThread.Join ();
// Marshal exceptions back to this thread.
if (this.returnException != null)
throw new CrossThreadException (this.returnException);
}
}
private void ProceedOnOtherThread (MethodInterceptionArgs args)
{
try
{
args.Proceed ();
}
catch (Exception ex)
{
this.returnException = ex;
}
}
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment