Мы используем этот фрагмент кода из StackOverflow для создания задачи, которая завершается сразу после успешного завершения первого набора задач. Из-за нелинейного характера его выполнения async/await не является действительно жизнеспособным, и поэтому этот код использует ContinueWith(). Она не определяет TaskScheduler, хотя, которого ряд из источников затронувших может быть опасно, потому что он использует TaskScheduler.Current когда большинство разработчиков обычно ожидают TaskScheduler.Default поведения от продолжений.
Преобладающая мудрость заключается в том, что вы всегда должны передавать явный TaskScheduler в ContinueWith. Тем не менее, я не видел четкого объяснения того, когда различные TaskSchedulers будут наиболее подходящими.
Каков конкретный пример случая, когда было бы лучше передать TaskScheduler.Current в ContinueWith(), а не TaskScheduler.Default? При принятии этого решения необходимо придерживаться правил?
Для контекста, здесь фрагмент кода, который я имею в виду:
public static Task<T> FirstSuccessfulTask<T>(IEnumerable<Task<T>> tasks)
{
var taskList = tasks.ToList();
var tcs = new TaskCompletionSource<T>();
int remainingTasks = taskList.Count;
foreach(var task in taskList)
{
task.ContinueWith(t =>
if(task.Status == TaskStatus.RanToCompletion)
tcs.TrySetResult(t.Result));
else
if(Interlocked.Decrement(ref remainingTasks) == 0)
tcs.SetException(new AggregateException(
tasks.SelectMany(t => t.Exception.InnerExceptions));
}
return tcs.Task;
}