public DispatcherOperationEvent(DispatcherOperation op, TimeSpan timeout) { _operation = op; _timeout = timeout; _event = new AutoResetEvent(false); // We will set our event once the operation is completed or aborted. _operation.Aborted += new EventHandler(OnCompletedOrAborted); _operation.Completed += new EventHandler(OnCompletedOrAborted); // Since some other thread is dispatching this operation, it could // have been dispatched while we were setting up the handlers. // We check the state again and set the event ourselves if this // happened. if (_operation._status != DispatcherOperationStatus.Pending && _operation._status != DispatcherOperationStatus.Executing) { _event.Set(); } }
// Note: we pass "exitWhenRequested=false" to the base // DispatcherFrame construsctor because we do not want to exit // this frame if the dispatcher is shutting down. This is // because we may need to invoke operations during the shutdown process. public DispatcherOperationFrame(DispatcherOperation op, TimeSpan timeout) : base(false) { _operation = op; // We will exit this frame once the operation is completed or aborted. _operation.Aborted += new EventHandler(OnCompletedOrAborted); _operation.Completed += new EventHandler(OnCompletedOrAborted); // We will exit the frame if the operation is not completed within // the requested timeout. if (timeout.Ticks > 0) { _waitTimer = new Timer(new TimerCallback(OnTimeout), null, timeout, new TimeSpan(-TimeSpan.TicksPerMillisecond)); /// Negative one (-1) milliseconds to disable periodic signaling. } // Some other thread could have aborted the operation while we were // setting up the handlers. We check the state again and mark the // frame as "should not continue" if this happened. if (_operation._status != DispatcherOperationStatus.Pending) { Exit(); } }
// Returns whether or not the operation was removed. internal bool Abort(DispatcherOperation operation) { bool notify = false; lock (_instanceLock) { if (operation.Status == DispatcherOperationStatus.Pending) { operation.Status = DispatcherOperationStatus.Aborted; notify = true; } } return notify; }
/// <summary> /// Executes the specified delegate asynchronously with the specified /// arguments, on the thread that the Dispatcher was created on. /// </summary> /// <param name="method"> /// A delegate to a method that takes parameters of the same number /// and type that are contained in the args parameter. /// </param> /// <param name="args"> /// An object to pass as the argument to the given method. /// This can be null if no arguments are needed. /// </param> /// <returns> /// A DispatcherOperation object that represents the result of the /// BeginInvoke operation. null if the operation could not be queued. /// </returns> public DispatcherOperation BeginInvoke(DispatcherOperationCallback method, object args) { if (method == null) { throw new ArgumentNullException("method"); } DispatcherOperation operation = null; if (!_hasShutdownFinished) { operation = new DispatcherOperation(this, method, args); // Add the operation to the work queue _queue.Enqueue(operation); // this will only cause at most 1 extra dispatcher loop, so // always set the event. _event.Set(); } return operation; }
/// <summary> /// Executes the specified delegate asynchronously with the specified /// arguments, on the thread that the Dispatcher was created on. /// </summary> /// <param name="method"> /// A delegate to a method that takes parameters of the same number /// and type that are contained in the args parameter. /// </param> /// <param name="args"> /// An object to pass as the argument to the given method. /// This can be null if no arguments are needed. /// </param> /// <returns> /// A DispatcherOperation object that represents the result of the /// BeginInvoke operation. null if the operation could not be queued. /// </returns> public DispatcherOperation BeginInvoke(DispatcherOperationCallback method, object args) { if (method == null) { throw new ArgumentNullException("method"); } DispatcherOperation operation = null; lock (_instanceLock) { if (!_hasShutdownFinished) { operation = new DispatcherOperation(this, method, args); // Add the operation to the work queue _queue.Enqueue(operation); // set the event only when the queue becomes non-empty, // the dispatcher only waits when the queue is empty, // so this makes it wake-up if (_queue.Count == 1) { _event.Set(); } } } return operation; }