public DfTask <TResult> Run <TResult>(Func <Task <TResult> > function) { var task = new DfTask <TResult>(); var currentListOfVisitedNodes = ListOfVisitedNodes.Current.Value ?? (ListOfVisitedNodes.Current.Value = new ListOfVisitedNodes()); var firstVisit = !currentListOfVisitedNodes.VisitedNodes.Contains(nodeId); if (firstVisit) { currentListOfVisitedNodes.VisitedNodes.Add(nodeId); } Func <Task> runAction = async() => { TResult result = default(TResult); Exception exception = null; try { result = await function(); } catch (Exception ex) { exception = ex; } ListOfVisitedNodes.Current.Value = currentListOfVisitedNodes; DfTask.AsyncBlockingTask = null; if (exception == null) { task.SetResult(result); } else { task.SetException(exception); } if (DfTask.AsyncBlockingTask != null) { await DfTask.AsyncBlockingTask; } }; Func <Task> actionToAddToCollection = Utilities.MakeActionRunInCurrentExecutionContextIfAny(runAction); ListOfVisitedNodes.Current.Value = null; if (firstVisit) { DfTask.AsyncBlockingTask = collection.AddAsync(actionToAddToCollection); } else { DfTask.AsyncBlockingTask = collectionForReentrantItems.AddAsync(actionToAddToCollection); } return(task); }
public DfTask Run(Func <Task> action) { var task = new DfTask(); var currentListOfVisitedNodes = ListOfVisitedNodes.Current.Value ?? (ListOfVisitedNodes.Current.Value = new ListOfVisitedNodes()); var firstVisit = !currentListOfVisitedNodes.VisitedNodes.Contains(nodeId); if (firstVisit) { currentListOfVisitedNodes.VisitedNodes.Add(nodeId); } Func <Task> runAction = async() => { Exception exception = null; try { if (cancellationToken.IsCancellationRequested) { exception = new OperationCanceledException(cancellationToken); } else { await action(); } } catch (Exception ex) { exception = ex; } ListOfVisitedNodes.Current.Value = currentListOfVisitedNodes; DfTask.AsyncBlockingTask = null; if (exception == null) { task.SetResult(); } else { task.SetException(exception); } if (DfTask.AsyncBlockingTask != null) { await DfTask.AsyncBlockingTask; } }; Func <Task> actionToAddToCollection = Utilities.MakeActionRunInCurrentExecutionContextIfAny(runAction); ListOfVisitedNodes.Current.Value = null; if (firstVisit) { DfTask.AsyncBlockingTask = collection.AddAsync(actionToAddToCollection); } else { DfTask.AsyncBlockingTask = collectionForReentrantItems.AddAsync(actionToAddToCollection); } return(task); }
public static DfTask <T[]> WhenAll <T>(params DfTask <T>[] tasks) { DfTask <T[]> resultTask = new DfTask <T[]>(); long totalCompleted = 0; long totalShouldComplete = tasks.Length; ConcurrentQueue <Exception> errors = new ConcurrentQueue <Exception>(); ConcurrentQueue <(int index, T value)> results = new ConcurrentQueue <(int index, T value)>(); TaskCompletionSource[] taskCompletionSources = new TaskCompletionSource[tasks.Length]; for (var index = 0; index < tasks.Length; index++) { var task = tasks[index]; taskCompletionSources[index] = new TaskCompletionSource(); int index1 = index; task.OnCompleted(() => { try { results.Enqueue((index1, task.GetResult())); } catch (Exception e) { errors.Enqueue(e); } if (Interlocked.Increment(ref totalCompleted) != totalShouldComplete) { AsyncBlockingTask = taskCompletionSources[index1].Task; } else { AsyncBlockingTask = null; if (errors.Count > 0) { resultTask.SetException(new AggregateException(errors.ToArray())); } else { resultTask.SetResult(results.OrderBy(x => x.index).Select(x => x.value).ToArray()); } if (AsyncBlockingTask != null) { for (int i = 0; i < tasks.Length; i++) { int i1 = i; if (i1 == index1) { continue; } AsyncBlockingTask.ContinueWith(t => taskCompletionSources[i1].TryCompleteFromCompletedTask(t)); } } else { for (int i = 0; i < tasks.Length; i++) { if (i == index1) { continue; } taskCompletionSources[i].SetResult(); } } } }); } return(resultTask); }