Created
October 26, 2012 10:53
-
-
Save kiwidev/3958178 to your computer and use it in GitHub Desktop.
SynchronizationContext that allows for catching and dealing with unhandled exceptions. Very useful in WinRT.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
using System; | |
using System.Threading; | |
namespace TestExceptions | |
{ | |
/// <summary> | |
/// Wrapper around a standard synchronization context, that catches any unhandled exceptions. | |
/// Acts as a facade passing calls to the original SynchronizationContext | |
/// </summary> | |
/// <example> | |
/// Set this up inside your App.xaml.cs file as follows: | |
/// <code> | |
/// protected override void OnActivated(IActivatedEventArgs args) | |
/// { | |
/// EnsureSyncContext(); | |
/// ... | |
/// } | |
/// | |
/// protected override void OnLaunched(LaunchActivatedEventArgs args) | |
/// { | |
/// EnsureSyncContext(); | |
/// ... | |
/// } | |
/// | |
/// private void EnsureSyncContext() | |
/// { | |
/// var exceptionHandlingSynchronizationContext = ExceptionHandlingSynchronizationContext.Register(); | |
/// exceptionHandlingSynchronizationContext.UnhandledException += OnSynchronizationContextUnhandledException; | |
/// } | |
/// | |
/// private void OnSynchronizationContextUnhandledException(object sender, UnhandledExceptionEventArgs args) | |
/// { | |
/// args.Handled = true; | |
/// } | |
/// </code> | |
/// </example> | |
internal class ExceptionHandlingSynchronizationContext : SynchronizationContext | |
{ | |
/// <summary> | |
/// Registration method. Call this from Launched and Loaded inside the App.xaml.cs | |
/// </summary> | |
/// <returns></returns> | |
public static ExceptionHandlingSynchronizationContext Register() | |
{ | |
var syncContext = SynchronizationContext.Current; | |
if (syncContext == null) | |
throw new InvalidOperationException("Ensure a synchronization context exists before calling this method."); | |
var customSynchronizationContext = syncContext as ExceptionHandlingSynchronizationContext; | |
if (customSynchronizationContext == null) | |
{ | |
customSynchronizationContext = new ExceptionHandlingSynchronizationContext(syncContext); | |
SynchronizationContext.SetSynchronizationContext(customSynchronizationContext); | |
} | |
return customSynchronizationContext; | |
} | |
private readonly SynchronizationContext _syncContext; | |
public ExceptionHandlingSynchronizationContext(SynchronizationContext syncContext) | |
{ | |
_syncContext = syncContext; | |
} | |
public override SynchronizationContext CreateCopy() | |
{ | |
return new ExceptionHandlingSynchronizationContext(_syncContext.CreateCopy()); | |
} | |
public override void OperationCompleted() | |
{ | |
_syncContext.OperationCompleted(); | |
} | |
public override void OperationStarted() | |
{ | |
_syncContext.OperationStarted(); | |
} | |
public override void Post(SendOrPostCallback d, object state) | |
{ | |
_syncContext.Post(WrapCallback(d), state); | |
} | |
public override void Send(SendOrPostCallback d, object state) | |
{ | |
_syncContext.Send(d, state); | |
} | |
private SendOrPostCallback WrapCallback(SendOrPostCallback sendOrPostCallback) | |
{ | |
return state => | |
{ | |
try | |
{ | |
sendOrPostCallback(state); | |
} | |
catch (Exception ex) | |
{ | |
if (!HandleException(ex)) | |
throw; | |
} | |
}; | |
} | |
private bool HandleException(Exception exception) | |
{ | |
if (UnhandledException == null) | |
return false; | |
var exWrapper = new UnhandledExceptionEventArgs() | |
{ | |
Exception = exception | |
}; | |
UnhandledException(this, exWrapper); | |
#if DEBUG && !DISABLE_XAML_GENERATED_BREAK_ON_UNHANDLED_EXCEPTION | |
if (global::System.Diagnostics.Debugger.IsAttached) global::System.Diagnostics.Debugger.Break(); | |
#endif | |
return exWrapper.Handled; | |
} | |
/// <summary> | |
/// Listen to this event to catch any unhandled exceptions and allow for handling them | |
/// so they don't crash your application | |
/// </summary> | |
public event EventHandler<UnhandledExceptionEventArgs> UnhandledException; | |
} | |
public class UnhandledExceptionEventArgs : EventArgs | |
{ | |
public bool Handled { get; set; } | |
public Exception Exception { get; set; } | |
} | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment