public static void RunSync(Action a) { if (isUnitTestingMode) { a(); return; } Exception exn = null; Debug.Assert(ctxt != null, "The SynchronizationContext must be captured before calling this method"); // Send on UI thread will execute immediately. ctxt.Send(ignore => { try { UIThread.MustBeCalledFromUIThread(); a(); } catch (Exception e) { exn = e; } }, null ); if (exn != null) { // throw exception on calling thread, preserve stacktrace if (!exn.Data.Contains(WrappedStacktraceKey)) { exn.Data[WrappedStacktraceKey] = exn.StackTrace; } throw exn; } }
// Runs the action on UI thread. Prevents from reentracy. public static void Run(Action action) { if (isUnitTestingMode) { action(); return; } Debug.Assert(ctxt != null, "The SynchronizationContext must be captured before calling this method"); #if DEBUG StackTrace stackTrace = new StackTrace(true); #endif #pragma warning disable VSTHRD001 // Avoid legacy thread switching APIs ctxt.Post(delegate(object ignore) #pragma warning restore VSTHRD001 // Avoid legacy thread switching APIs { UIThread.MustBeCalledFromUIThread(); ourUIQueue.Enqueue(action); if (ourIsReentrancy) { return; } ourIsReentrancy = true; try { while (ourUIQueue.Count > 0) { try { var a = ourUIQueue.Dequeue(); a(); } #if DEBUG catch (Exception e) { // swallow, random exceptions should not kill process Debug.Assert(false, string.Format("UIThread.Run caught and swallowed exception: {0}\n\noriginally invoked from stack:\n{1}", e.ToString(), stackTrace.ToString())); } #else catch (Exception) { // swallow, random exceptions should not kill process } #endif } } finally { ourIsReentrancy = false; } }, null); }