@ -10,16 +10,14 @@ namespace Microsoft.AspNet.SignalR.Infrastructure
{
internal static class CancellationTokenExtensions
{
private delegate CancellationTokenRegistration RegisterDelegate ( ref CancellationToken token , Action < object > callback , object state ) ;
private static readonly RegisterDelegate _tokenRegister = ResolveRegisterDelegate ( ) ;
public static IDisposable SafeRegister ( this CancellationToken cancellationToken , Action < object > callback , object state )
{
var callbackWrapper = new CancellationCallbackWrapper ( callback , state ) ;
// Ensure delegate continues to use the C# Compiler static delegate caching optimization.
CancellationTokenRegistration registration = _tokenRegister ( ref cancellationToken , InvokeCallback , callbackWrapper ) ;
CancellationTokenRegistration registration = cancellationToken . Register ( s = > Cancel ( s ) ,
callbackWrapper ,
useSynchronizationContext : false ) ;
var disposeCancellationState = new DiposeCancellationState ( callbackWrapper , registration ) ;
@ -27,7 +25,7 @@ namespace Microsoft.AspNet.SignalR.Infrastructure
return new DisposableAction ( s = > Dispose ( s ) , disposeCancellationState ) ;
}
private static void InvokeCallback ( object state )
private static void Cancel ( object state )
{
( ( CancellationCallbackWrapper ) state ) . TryInvoke ( ) ;
}
@ -37,56 +35,6 @@ namespace Microsoft.AspNet.SignalR.Infrastructure
( ( DiposeCancellationState ) state ) . TryDispose ( ) ;
}
[SuppressMessage("Microsoft.Design", "CA1031:DoNotCatchGeneralExceptionTypes", Justification = "This method should never throw since it runs as part of field initialzation")]
private static RegisterDelegate ResolveRegisterDelegate ( )
{
// The fallback is just a normal register that capatures the execution context.
RegisterDelegate fallback = ( ref CancellationToken token , Action < object > callback , object state ) = >
{
return token . Register ( callback , state ) ;
} ;
#if NETFX_CORE || PORTABLE
return fallback ;
# else
MethodInfo methodInfo = null ;
try
{
// By default we don't want to capture the execution context,
// since this is internal we need to create a delegate to this up front
methodInfo = typeof ( CancellationToken ) . GetMethod ( "InternalRegisterWithoutEC" ,
BindingFlags . NonPublic | BindingFlags . Instance ,
binder : null ,
types : new [ ] { typeof ( Action < object > ) , typeof ( object ) } ,
modifiers : null ) ;
}
catch
{
// Swallow this exception. Being extra paranoid, we don't want anything to break in case this dirty
// reflection hack fails for any reason
}
// If the method was removed then fallback to the regular method
if ( methodInfo = = null )
{
return fallback ;
}
try
{
return ( RegisterDelegate ) Delegate . CreateDelegate ( typeof ( RegisterDelegate ) , null , methodInfo ) ;
}
catch
{
// If this fails for whatever reason just fallback to normal register
return fallback ;
}
# endif
}
private class DiposeCancellationState
{
private readonly CancellationCallbackWrapper _callbackWrapper ;