Я работаю над приложением, в котором важно как можно быстрее вернуть данные в последовательный процесс, но может быть несколько источников для получения этих данных. Кроме того, иногда один источник работает быстрее, чем другой, но вы не знаете, какой это будет источник. Я использую ContinueWhenAny (...). Wait (), чтобы дождаться окончания первой Задачи, чтобы продолжить и вернуться из вызывающего метода. Тем не менее, мне нужно сначала проверить достоверность данных и только потом возвращать их (или если все задачи завершены и ни одна из них не имеет достоверных данных). Прямо сейчас мой код вернет даже недействительные данные, если это Задача, которая завершается первой.
Есть ли способ сделать что-то вроде «ContinueWhenAny», но только когда Task.Result удовлетворяет определенному условию, в противном случае дождитесь следующей задачи / и т. Д., Пока последняя задача не завершится?
Кроме того, мне нужно убедиться, что после того, как один результат верен, другие потоки отменяются. Эта часть уже работает нормально.
В настоящее время мой код выглядит следующим образом (без обработки исключений, только гайки и болты):
ResultObject result = null;
var tokenSource = new CancellationTokenSource();
var tasks = listOfSources
.Select(i => Task.Factory.StartNew(
() =>
{
i.CancellationToken = tokenSource.Token;
//Database Call
return i.getData(inputparameters);
}, tokenSource.Token));
Task.Factory.ContinueWhenAny(
tasks.ToArray(),
firstCompleted =>
{
//This is the "result" I need to validate before setting and canceling the other threads
result = firstCompleted.Result;
tokenSource.Cancel();
}).Wait();
return result;
Есть идеи? Я не хочу использовать ContinueWhenAll, поскольку, если первый вызов занимает 2 секунды, а второй - 10 секунд, я хочу вернуться к последовательному процессу через 2 секунды, если первый вызов возвращает действительные данные, в противном случае подождите 10 секунд, надеюсь, что Результат имеет действительные данные и возвращает недействительные данные только в том случае, если все задачи выполнены, и возвращает неверный результат.
--------- ОБНОВЛЕНИЕ ----
Спасибо zmbq за отличную идею. Обновленный (рабочий) код приведен ниже и отвечает всем моим требованиям. Однако, одно предостережение: разница между этим кодом и предыдущим кодом заключается в том, что этот код будет возвращать нулевой результат, если ни одна из задач не выдаст действительный результат, а не предыдущий код, который сам возвращает неверный результат. Нетрудно изменить эту версию, чтобы сделать это тоже, но я вполне доволен, возвращая в этом случае ноль для моих целей.
ResultObject result = null;
var tokenSource = new CancellationTokenSource();
var tasks = listOfSources
.Select(i => Task.Factory.StartNew(
() =>
{
i.CancellationToken = tokenSource.Token;
//Database Call
return i.getData(inputparameters);
}, tokenSource.Token)).ToArray();
result = GetFirstValidResult(tokenSource,tasks);
return result;
private ResultObject GetFirstValidResult(CancellationTokenSource tokenSource, Task<ResultObject>[] tasks)
{
ResultObject result = null;
Task.Factory.ContinueWhenAny(
tasks,
firstCompleted =>
{
var testResult = firstCompleted.Result;
if(testResult != null && testResult.IsValid())
{
result = testResult;
tokenSource.Cancel();
}
else
{
var remainingTasks = tasks.Except(new[]{firstCompleted}).ToArray();
if(remainingTasks.Any())
{
result = GetFirstValidResult(tokenSource, remainingTasks);
}
}
}).Wait();
return result;
}