在他PluralSight當然異步C#5,喬恩斯基特提供了名爲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.");
}
}
在this question,馬丁尼爾提供了一個看似更優雅,使用產量回報
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);
}
}
是仍有些新來的鑽機實施異步編程的我們,任何人都可以描述可能與馬丁·尼爾的實施出現的具體問題是正確的喬恩斯基特的更復雜的實施
@MickyD:沒錯;但我毫不猶豫地將代碼量翻了近四倍,直到我明白,至少在廣泛的筆觸中,爲什麼。 ** usr **在下面給我提供了兩個很好的理由。 –
同意。我剛剛遇到了「看似更優雅」的問題。在編程的各個方面,不能總是將行數與優雅等同起來。 Servy在下面提出了一些好的觀點。 :) – MickyD