这并不像我认为的那样需要很简单,启动一些任务来对对象进行操作。每个任务一个唯一的对象。当每个任务报告结果时,第二部分是ContinueWith
。但是,我没有得到WhenAll
类型的行为。希望有人可以让我直截了当。
_tasks = new Task<AnalysisResultArgs>[_beansList.Count];
for (int loopCnt = 0; loopCnt < _beansList.Count; loopCnt++)
{
_tasks[loopCnt] = Task<AnalysisResultArgs>.Factory.StartNew(() =>
{
return _beansList[loopCnt].Analyze(newBeanData);
});
await _tasks[loopCnt].ContinueWith(ReportResults,
TaskContinuationOptions.RunContinuationsAsynchronously)
// do some housekeeping when all tasks are complete
}
private void ReportResults(Task<AnalysisResultArgs> task)
{
/* Do some serial operations
}
我的理解是,_beansList.Count
任务将会启动,并且await
上的ContinueWith
将执行内务工作,直到所有任务完成为止。我无法阻止,因为我需要确保能够限制传入的数据以防止太多的任务等待执行。
我在哪里,等待实际完成,并且即使并非所有任务都已完成,家务也会运行。
答案 0 :(得分:2)
您没有等待所有任务,等待循环继续。您应该使用Task.WhenAll
方法。另外,如果你可以在任务中运行它,为什么还需要延续?像这样简化您的代码:
private void ReportResults(AnalysisResultArgs results)
{
/* Do some serial operations */
}
...
_tasks = new Task<AnalysisResultArgs>[_beansList.Count];
for (int loopCnt = 0; loopCnt < _beansList.Count; loopCnt++)
{
var count = loopCnt;
_tasks[count] = Task.Run(() =>
{
var results = _beansList[count].Analyze(newBeanData);
ReportResults(results);
return results;
});
}
// do some housekeeping when all tasks are complete
await Task.WhenAll(_tasks);
答案 1 :(得分:1)
正如@Stephen已经提到的,问题中的代码不是最小的,完整的和可验证的。我冒昧地做了一些假设,这就是我认为你的代码应该是这样的:
public async Task<AnalysisResultArgs[]> MainMethod()
{
var _beansList = new List<AnalysisResultArgs>();
for(int i=0; i< 99; i++) // Considering 100 records
_beansList.Add(new AnalysisResultArgs());
var _tasks = new Task<AnalysisResultArgs>[_beansList.Count];
for (int loopCnt = 0; loopCnt < _beansList.Count; loopCnt++)
{
var local = loopCnt;
_tasks[local] = Task.Run(async() => await ReportResults(_beansList[local].Analyze(new AnalysisResultArgs())));
}
return await Task.WhenAll(_tasks);
}
private async Task<AnalysisResultArgs> ReportResults(Task<AnalysisResultArgs> task)
{
await Task.Delay(1000);
return await Task.FromResult(new AnalysisResultArgs());
}
public class AnalysisResultArgs
{
public async Task<AnalysisResultArgs> Analyze(AnalysisResultArgs newBeanData)
{
await Task.Delay(1000);
return await Task.FromResult(new AnalysisResultArgs());
}
}
假设/其他细节:
Task.Delay
和Task.FromResult
仅仅是实际逻辑的持有者。Analyze
和ReportResults
中的所有方法均为Async 在循环代码中可能是:
_tasks[local] = ReportResults(_beansList[local].Analyze(new
AnalysisResultArgs()));
但是如果我们使用Task.Run
来启动Task
,那么async, await
有助于释放调用线程池线程/同步上下文。它有助于提高系统的可扩展性。
_beansList
属于List<AnalysisResultArgs>
类型,但可以根据实际需求进行修改 ReportResults
以获取Func<Task<AnalysisResultArgs>> func
,而不是简单的d Task<AnalysisResultArgs>
,从而在方法中执行await func()
,然后调用代码可以真是异步如下:
_tasks[local] = Task.Run(async() => await ReportResults(async() => await
_beansList[local].Analyze(new AnalysisResultArgs())));