C# 将ContinueWith与多个任务一起使用
这并不像我想象的那样,需要简单,启动一些任务来对一个对象执行操作。每个任务有一个唯一的对象。第二部分是在每个任务报告结果时与连续体。然而,我没有得到一个C# 将ContinueWith与多个任务一起使用,c#,async-await,task-parallel-library,C#,Async Await,Task Parallel Library,这并不像我想象的那样,需要简单,启动一些任务来对一个对象执行操作。每个任务有一个唯一的对象。第二部分是在每个任务报告结果时与连续体。然而,我没有得到一个whalll类型的行为。希望有人能纠正我的错误 _tasks = new Task<AnalysisResultArgs>[_beansList.Count]; for (int loopCnt = 0; loopCnt < _beansList.Count; loopCnt++) { _tasks[loopCnt] =
whalll
类型的行为。希望有人能纠正我的错误
_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
}
\u tasks=新任务[\u beansList.Count];
对于(int loopCnt=0;loopCnt<\u beansList.Count;loopCnt++)
{
_tasks[loopCnt]=Task.Factory.StartNew(()=>
{
返回_beansList[loopCnt].Analyze(newBeanData);
});
等待任务[loopCnt]。继续(报告结果,
TaskContinuationOptions.RunContinuationsAsynchronously)
//完成所有任务后,进行一些内务管理
}
私有void报告结果(任务)
{
/*做一些串行操作
}
据我所知,将启动\u beansList.Count
任务,并通过使用ContinueWith
上的等待
,在所有任务完成之前不会执行内务工作。我无法阻止,因为我需要确保能够限制传入的数据,以防止太多的任务等待执行
我在哪里搞砸了,等待实际上已经完成,而且内务管理也在运行,即使不是所有的任务都已运行到完成。您不是在等待所有的任务,而是在循环中等待继续。您应该使用
Task.whalll
方法进行此操作。另外,如果可以在任务内部运行,为什么需要继续?将代码简化如下:
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);
private void ReportResults(AnalysisResultArgs结果)
{
/*做一些串行操作*/
}
...
_任务=新任务[_beansList.Count];
对于(int loopCnt=0;loopCnt<\u beansList.Count;loopCnt++)
{
var计数=loopCnt;
_任务[计数]=任务。运行(()=>
{
变量结果=_beansList[count]。分析(newbeansdata);
报告结果(结果);
返回结果;
});
}
//完成所有任务后,进行一些内务管理
等待任务。当所有(_任务);
您不是在等待所有任务,而是在循环中等待继续。您应该使用Task.whalll
方法进行此操作。另外,如果可以在任务内部运行,为什么需要继续?将代码简化如下:
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);
private void ReportResults(AnalysisResultArgs结果)
{
/*做一些串行操作*/
}
...
_任务=新任务[_beansList.Count];
对于(int loopCnt=0;loopCnt<\u beansList.Count;loopCnt++)
{
var计数=loopCnt;
_任务[计数]=任务。运行(()=>
{
变量结果=_beansList[count]。分析(newbeansdata);
报告结果(结果);
返回结果;
});
}
//完成所有任务后,进行一些内务管理
等待任务。当所有(_任务);
正如@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.Run
启动任务
,那么async,wait
有助于释放调用线程池线程/同步上下文。它有助于提高系统的可伸缩性
\u beansList
为List
类型,但可根据实际需求进行修改ReportResults
可以修改为接受Func
,而不是简单的d任务
,从而在方法内部执行wait Func()
,然后调用代码可以真正异步,如下所示:
_tasks[local] = Task.Run(async() => await ReportResults(async() => await
_beansList[local].Analyze(new AnalysisResultArgs())));
正如@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.Run
启动任务
,那么async,wait
有助于释放调用线程池线程/同步上下文。它有助于提高系统的可伸缩性
\u beansList
为List
类型,但可根据实际需求进行修改ReportResults
可以修改为接受Func
,而不是简单的d任务
,从而在方法内部执行wait Func()
,然后调用代码可以真正异步,如下所示:
_tasks[local] = Task.Run(async() => await ReportResults(async() => await
_beansList[local].Analyze(new AnalysisResultArgs())));
请减少到一个最小的例子是完整的,并再现问题。旁注:如果您使用
Task.Run
而不是StartNew
,使用wait
而不是ContinueWith
,那么您的代码将更干净,表现更好。Stephen,我感谢您在这个问题上的评论和公认的权威,不过,这是一个最简单的示例,减去一些额外的类。你对Task.Run而不是StartNew的声明,使用Wait(我这么做了)而不是ContinueWith,我会看看我是否可以在网上搜索为什么这样更好。我认为ContinueWith就是这个意思,而wait就是它所说的。若要解释“开始一项新任务”,请在任务完成后继续执行第二步。等到所有的都完成了,这个例子还不完整。我无法将其粘贴到新项目中并在调试器中观察其行为。我在和上有博客帖子。@StephenCleary我有好几次这样的博客,他们帮了我很大的忙。不,您不能将其粘贴到项目中并单步执行。我为此道歉。尽管如此,您的评论和Thours的评论还是帮了大忙。请简化为一个完整的、再现问题的最小示例。旁注:如果您使用Task.Run
而不是StartNew
,使用wait
而不是ContinueWith
,那么您的代码将更干净,表现更好。Stephen,我感谢您的评论和记录