Is there any reason to prefer one of these implementations over another

In his PluralSight Asynchronous C # 5 course, Jon Skeet provides this implementation for a convenience extension method called InCOmpletionOrder:

public static IEnumerable<Task<T>> InCompletionOrder<T>(this IEnumerable<Task<T>> source) { var inputs = source.ToList(); var boxes = inputs.Select(x => new TaskCompletionSource<T>()).ToList(); int currentIndex = -1; foreach (var task in inputs) { task.ContinueWith(completed => { var nextBox = boxes[Interlocked.Increment(ref currentIndex)]; PropagateResult(completed, nextBox); }, TaskContinuationOptions.ExecuteSynchronously); } return boxes.Select(box => box.Task); } private static void PropagateResult<T>(Task<T> completedTask, TaskCompletionSource<T> completionSource) { switch(completedTask.Status) { case TaskStatus.Canceled: completionSource.TrySetCanceled(); break; case TaskStatus.Faulted: completionSource.TrySetException(completedTask.Exception.InnerExceptions); break; case TaskStatus.RanToCompletion: completionSource.TrySetResult(completedTask.Result); break; default: throw new ArgumentException ("Task was not completed."); } } 

In this matter, Martin Neal provides a seemingly more elegant return-return implementation.

 public static IEnumerable<Task<T>> InCompletionOrder<T>(this IEnumerable<Task<T>> source) { var tasks = source.ToList(); while (tasks.Any()) { var t = Task.WhenAny(tasks); yield return t.Result; tasks.Remove(t.Result); } } 

While still somewhat new to harsh asynchronous programs, can anyone describe the specific problems that may arise during the implementation of Martin Neal, which are properly resolved by John Skeet, more involved in the implementation

+5
source share
1 answer

The second solution has a quadratic time complexity problem. The loop runs N times, and each call to WhenAny adds N to these tasks. Do not use this code unless you know for sure that the number of tasks is very small.

The call to Remove also causes quadratic time complexity.

In addition, the second part of the code blocks. You only return tasks as they are completed. InCompletionOrder gives you these tasks immediately, and they end later.

I would consider InCompletionOrder as a library method. Put it in the utility file and this will not cause maintenance problems. This behavior will never change. I do not see the size of the code here.

+5
source

Source: https://habr.com/ru/post/1242458/


All Articles