Мы используем этот фрагмент кода из 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;
}