Пример #1
0
        public void OnFileChanged(TrackedFileEventArgs file)
        {
            if (CancellationToken.IsCancellationRequested)
            {
                return;
            }

            var filePath = file.Path;

            ICancellableTask task = null;

            // Check if we have an outstanding line count task. If we don't, kick one off
            lock (OutstandingLineCounts)
            {
                if (!OutstandingLineCounts.ContainsKey(filePath))
                {
                    // kick off and add line count task
                    task = CancellableTaskRunner.Run(async token =>
                    {
                        await CalculateLineCount(filePath, token);
                    }, onThreadPoolThread: true);

                    OutstandingLineCounts.Add(filePath, task);
                }
            }

            task?.Task.ContinueWith(t =>
            {
                if (t.IsFaulted)
                {
                    OnLineCountFailed?.Invoke(new LineCountFailedEventArgs(filePath, t.Exception));
                }
            });
        }
Пример #2
0
        public void CancelTask(ICancellableTask cancelledTask)
        {
            var task = _scheduledTasks.SingleOrDefault(t => t.TaskId == cancelledTask.Id);

            if (task == null)
            {
                throw new NullReferenceException($"TaskId {cancelledTask.Id} could not be found");
            }
            task.Cancel();
        }
Пример #3
0
        /// <summary>
        /// Waits for all of the passed in tasks to complete successfully or for any to fault or be canceled.
        /// If any fault or are canceled, all the tasks are canceled.
        /// If all complete successfully, the returned task is successful.
        /// If any task faults, the returned task's Exception property is an AggregateException that
        /// contains exceptions from all the tasks that faulted. If waitForCancellations is false, it will only contain exceptions
        /// from the first faulting task.
        /// If waitForCancellations is true and no task faulted but at least one was canceled, the returned task
        /// will be in the canceled state with the CancellationToken associated with the task.
        /// If waitForCancellations is false, with the first task canceled the returned task will be in the canceled
        /// state with the CancellationToken associated with the task.
        /// </summary>
        /// <param name="tasks"></param>
        /// <param name="waitForCancellations">If true, wait for all tasks to complete one way or another,
        /// whether successfully, faulted, or canceled, before the returned task becomes successful, faulted, or canceled.
        /// If false, then after any fault or cancellation, all tasks are cancelled and the returned task immediately
        /// becomes faulted or canceled without waiting for the other tasks to go into their cancelled state or fault.</param>
        public static Task WhenAllCancelOnFirstException(IEnumerable <ICancellableTask> tasks, bool waitForCancellations = true)
        {
            TaskCompletionSource <object> tcs = new TaskCompletionSource <object>();

            List <ICancellableTask> tasksList = tasks.ToList();

            if (tasksList.Count == 0)
            {
                tcs.SetResult(null);
                return(tcs.Task);
            }

            object           continuationLock         = new object();
            int              tasksCompleteInAnyManner = 0;
            ICancellableTask firstTaskCanceled        = null;
            List <Exception> exceptions          = new List <Exception>();
            bool             cancellationsIssued = false;
            bool             waitTaskCompleted   = false;

            foreach (ICancellableTask cancellableTask in tasks)
            {
                cancellableTask.Task.ContinueWith(task =>
                {
                    lock (continuationLock)
                    {
                        // Don't bother doing the bookkeeping if we've already signaled the task.
                        if (waitTaskCompleted)
                        {
                            return;
                        }

                        tasksCompleteInAnyManner++;

                        if (task.IsFaulted)
                        {
                            exceptions.AddRange(task.Exception.InnerExceptions);
                        }

                        if (task.IsCanceled && firstTaskCanceled == null)
                        {
                            for (int i = 0; i < tasksList.Count; i++)
                            {
                                if (tasksList[i].Task == task)
                                {
                                    firstTaskCanceled = tasksList[i];
                                }
                            }
                        }

                        if (tasksCompleteInAnyManner == tasksList.Count)
                        {
                            // If all tasks finished but some faulted, set the exceptions for the wait task
                            if (exceptions.Count > 0)
                            {
                                tcs.SetException(exceptions);
                                waitTaskCompleted = true;
                            }
                            // If all tasks finished, none faulted, but at least one was canceled, set wait task as canceled
                            else if (firstTaskCanceled != null)
                            {
                                tcs.TrySetCanceled(firstTaskCanceled.CancellationTokenSource.Token);
                                waitTaskCompleted = true;
                            }
                            // If everything succeeded, signal the wait task as successful
                            else
                            {
                                tcs.SetResult(null);
                                waitTaskCompleted = true;
                            }
                        }
                        else if (!waitForCancellations)
                        {
                            // If a task faulted and we're not waiting for all the tasks to finish their cancellation,
                            // set the exceptions for the wait task.
                            if (task.IsFaulted)
                            {
                                tcs.SetException(exceptions);
                                waitTaskCompleted = true;
                            }
                            // If a task canceled and we're not waiting for all the tasks to finish their cancellation,
                            // set the wait task as canceled
                            else if (task.IsCanceled)
                            {
                                tcs.TrySetCanceled(firstTaskCanceled.CancellationTokenSource.Token);
                                waitTaskCompleted = true;
                            }
                        }

                        // Cancel all tasks if any task faults or is canceled.
                        // Do this last because the continuation for the tasks we're cancelling can run
                        // synchronously if the task has not been started yet and is associated with a
                        // cancellation token.
                        if ((task.IsCanceled || task.IsFaulted) && !cancellationsIssued)
                        {
                            cancellationsIssued = true;

                            foreach (ICancellableTask taskToCancel in tasks)
                            {
                                taskToCancel.Cancel();
                            }
                        }
                    }
                }, TaskContinuationOptions.ExecuteSynchronously);
            }

            return(tcs.Task);
        }
Пример #4
0
 public static void Cancel(this ICancellableTask cancellableTask)
 {
     cancellableTask.CancellationTokenSource.Cancel();
 }