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; } }
public int DoIdle(IOleComponentManager mgr) { UIThread.MustBeCalledFromUIThread(); Debug.Assert(!this.isDisposed, "tried to do idle work on a disposed TaskReporter"); lock (queueLock) { // process up to MAX items at a time int MAX = 50; // How to pick a value? I tried a couple values with a project with many errors, and this value seems to work well. This value is also happy for unit tests. while (work.Count != 0 && mgr.FContinueIdle() != 0) { int i = 0; while (work.Count != 0 && i < MAX) { Action workItem = work.Dequeue(); workItem(); ++i; } } if (work.Count != 0) { return(1); } else { return(0); } } }
public void Dispose(bool dispose) { UIThread.MustBeCalledFromUIThread(); lock (queueLock) { if (!this.isDisposed) { if (dispose) { TaskReporterIdleRegistration.Unregister(this.token); FinishProcessingQueue(); foreach (TaskInfo ti in this.backgroundTasks) { ti.Dispose(); } foreach (TaskInfo ti in this.buildTasks) { ti.Dispose(); } this.ClearAllTasks(); if (null != this.taskListProvider) { this.taskListProvider.Refresh(); this.taskListProvider.Clear(); } } this.buildTasks = null; this.backgroundTasks = null; this.taskListProvider = null; this.isDisposed = true; } } }
public static uint Register(TaskReporter tr) { UIThread.MustBeCalledFromUIThread(); uint n = nextToken++; taskReporters.Add(n, tr); return(n); }
private void FinishProcessingQueue() { UIThread.MustBeCalledFromUIThread(); lock (queueLock) { while (work.Count != 0) { Action workItem = work.Dequeue(); workItem(); } } }
public void Dispose() { UIThread.MustBeCalledFromUIThread(); lock (queueLock) { this.Dispose(true); #if DEBUG Interlocked.Decrement(ref AliveCount); #endif GC.SuppressFinalize(this); } }
// 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); }
// The language service calls this periodically when the UI thread is idle public static int DoIdle(IOleComponentManager mgr) { UIThread.MustBeCalledFromUIThread(); int result = 0; foreach (TaskReporter tr in taskReporters.Values) { result = tr.DoIdle(mgr); if (result != 0) { break; } } return(result); }
public static void Unregister(uint n) { UIThread.MustBeCalledFromUIThread(); taskReporters.Remove(n); }