![](/img/trans.png)
[英]How to execute a number of tasks in parallel, and return ASAP when a task completes with a specific result?
[英]How do I execute multiple Tasks using Task Parallel Library and return after the first one to actually return data
我正在開發一個應用程序,在該應用程序中,盡快將數據返回串行過程很重要,但是可以有多個來源來獲取數據。 同樣,有時一個來源要比另一個來源快,但您不知道將是哪個來源。 我正在使用ContinueWhenAny(...)。Wait()等待第一個Task結束,以便繼續並退出調用方法。 但是,我需要先檢查數據的有效性,然后才返回(或者如果所有任務都已完成並且它們都沒有有效數據)。 現在,如果那是最先完成的任務,我的代碼甚至會返回無效數據。
是否有一種方法可以執行類似“ 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的好主意。 更新后的(工作)代碼在下面,並且滿足我的所有要求。 請注意,此代碼與先前的代碼之間的區別在於,如果沒有一個Task產生有效結果,則此代碼將返回空結果,而不是先前的代碼本身返回無效結果。 更改此版本也不難,但是出於我的目的,我很滿意在這種情況下返回null。
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;
}
好吧,如果您的firstCompleted回調函數將檢查結果,並在其余任務上調用ContinueWhenAny,以防結果不合法,那么您就可以完成。
與往常一樣,我建議您看一下ZeroMQ 。 觸發任務,並讓每個任務將消息寫入輸出隊列(如果結果合法)。 主線程將阻塞隊列,並在收到有效消息或所有任務已經完成時返回。
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.