private void NotifyEditors(NormalizedSnapshotSpanCollection changes, TaggerDelay delay) { _tagSource.AssertIsForeground(); if (changes.Count == 0) { // nothing to do. return; } if (delay == TaggerDelay.NearImmediate) { // if delay is immediate, we let notifier knows about the change right away _batchChangeNotifier.EnqueueChanges(changes); return; } // if delay is anything more than that, we let notifier knows about the change after given delay // event notification is only cancellable when disposing of the tagger. _tagSource.RegisterNotification( () => _batchChangeNotifier.EnqueueChanges(changes), (int)delay.ComputeTimeDelay(_subjectBuffer).TotalMilliseconds, _cancellationTokenSource.Token ); }
public void EnqueueWork( Func <Task> workAsync, TaggerDelay delay, IAsyncToken asyncToken, CancellationToken cancellationToken) { lock (this) { _eventWorkQueue = _eventWorkQueue.ContinueWithAfterDelayFromAsync( _ => workAsync(), cancellationToken, (int)delay.ComputeTimeDelay().TotalMilliseconds, TaskContinuationOptions.None, TaskScheduler.Default).CompletesAsyncOperation(asyncToken); } }
private void EnqueueNotificationRequest(TaggerDelay delay) { AssertIsForeground(); if (_notificationRequestEnqueued) { // we already have a pending task to update the UI. No need to do anything at this // point. return; } var currentTick = Environment.TickCount; if ( Math.Abs(currentTick - _lastReportTick) > TaggerDelay.NearImmediate.ComputeTimeDelay(_subjectBuffer).TotalMilliseconds ) { _lastReportTick = currentTick; this.NotifyEditor(); } else { // enqueue a task to update the UI with all the changed spans at some time in the // future. _notificationRequestEnqueued = true; // Note: this operation is uncancellable. We already updated our internal state in // RecomputeTags. We must eventually notify the editor about these changes so that the // UI reaches parity with our internal model. Also, if we cancel it, then // 'reportTagsScheduled' will stay 'true' forever and we'll never notify the UI. _notificationService.RegisterNotification( () => { AssertIsForeground(); // First, clear the flag. That way any new changes we hear about will enqueue a task // to run at a later point. _notificationRequestEnqueued = false; this.NotifyEditor(); }, (int)delay.ComputeTimeDelay(_subjectBuffer).TotalMilliseconds, _listener.BeginAsyncOperation("EnqueueNotificationRequest"), _cancellationToken ); } }
// We may get a flurry of 'Notify' calls if we've enqueued a lot of work and it's now just // completed. Batch up all the notifications so we can tell the editor about them at the // same time. private void EnqueueNotificationRequest( TaggerDelay delay) { AssertIsForeground(); if (_notificationRequestEnqueued) { // we already have a pending task to update the UI. No need to do anything at this // point. return; } var currentTick = Environment.TickCount; if (Math.Abs(currentTick - _lastReportTick) > _throttleDelay.ComputeTimeDelay(_subjectBuffer)) { _lastReportTick = currentTick; this.NotifyEditor(); } else { // enqueue a task to update the UI with all the changed spans at some time in the // future. _notificationRequestEnqueued = true; // Note: this operation is uncancellable. We already updated our internal state in // RecomputeTags. We must eventually notify the editor about these changes so that the // UI reaches parity with our internal model. Also, if we cancel it, then // 'reportTagsScheduled' will stay 'true' forever and we'll never notify the UI. _notificationService.RegisterNotification(() => { AssertIsForeground(); // First, clear the flag. That way any new changes we hear about will enqueue a task // to run at a later point. _notificationRequestEnqueued = false; this.NotifyEditor(); }, delay.ComputeTimeDelay(_subjectBuffer), _listener.BeginAsyncOperation("EnqueueNotificationRequest")); } }