/// <summary> /// Schedules the provided handler on the dispatcher. /// </summary> /// <param name="priority">The execution priority for the handler</param> /// <param name="handler">The handler to execute</param> /// <returns>An async operation for the scheduled handler.</returns> public UIAsyncOperation RunAsync(CoreDispatcherPriority priority, CancellableDispatchedHandler handler) { UIAsyncOperation operation = null; DispatchedHandler nonCancellableHandler = () => handler(operation.Token); return(operation = EnqueueOperation(priority, nonCancellableHandler)); }
/// <summary> /// Run operation with 'animation' priority, prior to layout and draw calls. This will run at the beginning of the next UI pass. /// </summary> internal UIAsyncOperation RunAnimation(DispatchedHandler handler) { var operation = new UIAsyncOperation(handler, null); ImmutableInterlocked.Enqueue(ref _animationQueue, operation); QueueOperations(); return(operation); }
/// <summary> /// Schedules the provided handler on the dispatcher. /// </summary> /// <param name="priority">The execution priority for the handler</param> /// <param name="handler">The handler to execute</param> /// <returns>An async operation for the scheduled handler.</returns> /// <remarks>Can only be invoked on the UI thread</remarks> internal UIAsyncOperation RunAsync(CoreDispatcherPriority priority, CancellableDispatchedHandler handler) { CoreDispatcher.CheckThreadAccess(); UIAsyncOperation operation = null; DispatchedHandler nonCancellableHandler = () => handler(operation.Token); return(operation = EnqueueOperation(priority, nonCancellableHandler)); }
private UIAsyncOperation EnqueueOperation(CoreDispatcherPriority priority, DispatchedHandler handler) { EventActivity scheduleActivity = null; if (_trace.IsEnabled) { scheduleActivity = _trace.WriteEventActivity( TraceProvider.CoreDispatcher_Schedule, EventOpcode.Send, new[] { ((int)priority).ToString(), handler.Method.DeclaringType.FullName + "." + handler.Method.DeclaringType.Name } ); } var operation = new UIAsyncOperation(handler, scheduleActivity); if (priority < CoreDispatcherPriority.Idle || priority > CoreDispatcherPriority.High) { throw new ArgumentException($"The priority {priority} is not supported"); } var queue = GetQueue(priority); bool shouldEnqueue; lock (_gate) { queue.Enqueue(operation); shouldEnqueue = IncrementGlobalCount() == 1; } if (shouldEnqueue) { EnqueueNative(); } return(operation); }
private void DispatchItems() { UIAsyncOperation operation = null; CoreDispatcherPriority operationPriority = CoreDispatcherPriority.Normal; for (int i = 3; i >= 0; i--) { var queue = _queues[i]; lock (_gate) { if (queue.Count > 0) { operation = queue.Dequeue(); operationPriority = (CoreDispatcherPriority)(i - 2); if (DecrementGlobalCount() > 0) { EnqueueNative(); } break; } } } if (operation != null) { if (!operation.IsCancelled) { IDisposable runActivity = null; try { if (_trace.IsEnabled) { runActivity = _trace.WriteEventActivity( TraceProvider.CoreDispatcher_InvokeStart, TraceProvider.CoreDispatcher_InvokeStop, relatedActivity: operation.ScheduleEventActivity, payload: new[] { ((int)operationPriority).ToString(), operation.GetDiagnosticsName() } ); } using (runActivity) { using (CoreDispatcherSynchronizationContext.Apply(this, operationPriority)) { operation.Action(); operation.Complete(); } } } catch (Exception ex) { if (_trace.IsEnabled) { _trace.WriteEvent(TraceProvider.CoreDispatcher_Exception, EventOpcode.Send, new[] { ex.GetType().ToString(), operation.GetDiagnosticsName() }); } operation.SetError(ex); this.Log().Error("Dispatcher unhandled exception", ex); } } else { if (_trace.IsEnabled) { _trace.WriteEvent(TraceProvider.CoreDispatcher_Cancelled, EventOpcode.Send, new[] { operation.GetDiagnosticsName() }); } } } else { throw new InvalidOperationException("Dispatch queue is empty"); } }
private void DispatchItems() { UIAsyncOperation operation = null; var operationPriority = CoreDispatcherPriority.Normal; Rendering?.Invoke(null, RenderingEventArgsGenerator(DateTimeOffset.UtcNow - _startTime)); var didEnqueue = false; for (var i = 3; i >= 0; i--) { var queue = _queues[i]; lock (_gate) { if (queue.Count > 0) { operation = queue.Dequeue(); operationPriority = (CoreDispatcherPriority)(i - 2); if (DecrementGlobalCount() > 0) { didEnqueue = true; EnqueueNative(); } break; } } } if (operation != null) { if (!operation.IsCancelled) { IDisposable runActivity = null; try { if (_trace.IsEnabled) { runActivity = _trace.WriteEventActivity( TraceProvider.CoreDispatcher_InvokeStart, TraceProvider.CoreDispatcher_InvokeStop, relatedActivity: operation.ScheduleEventActivity, payload: new[] { ((int)operationPriority).ToString(), operation.GetDiagnosticsName() } ); } using (runActivity) { using (GetSyncContext(operationPriority).Apply()) { operation.Action(); operation.Complete(); } } } catch (Exception ex) { if (_trace.IsEnabled) { _trace.WriteEvent(TraceProvider.CoreDispatcher_Exception, EventOpcode.Send, new[] { ex.GetType().ToString(), operation.GetDiagnosticsName() }); } operation.SetError(ex); this.Log().Error("Dispatcher unhandled exception", ex); } } else { if (_trace.IsEnabled) { _trace.WriteEvent(TraceProvider.CoreDispatcher_Cancelled, EventOpcode.Send, new[] { operation.GetDiagnosticsName() }); } } } else if (!ShouldRaiseRenderEvents) { if (this.Log().IsEnabled(Microsoft.Extensions.Logging.LogLevel.Debug)) { this.Log().Error("Dispatch queue is empty"); } } if (!didEnqueue && ShouldRaiseRenderEvents) { DispatchWakeUp(); } }