为什么是任务?WaitAll不等待所有任务完成?c#
本文关键字:任务 WaitAll 为什么 等待 | 更新日期: 2023-09-27 18:05:26
开始之前。我看过类似的问题,我不认为他们有一个答案在我的情况。
我在使用Task.Factory.StartNew和Task.WaitAll时遇到了问题。
我在任务中初始化的已创建类中的对象上获得空异常,即使抛出空异常的代码应该等到所有任务完成。
如果我在没有任务的情况下运行这段代码,它可以正常工作。
为什么是Task。WaitAll不等待所有任务完成?
Queue<Task> tasks = new Queue<Task>();
//Go through all transactions in the file via the reader.
foreach (transaction t in xr.read_x12(_progressbar_all_processing)) {
tasks.Enqueue(Task.Factory.StartNew(() => {
//Create a new provider from the current transaction and then
//add it to the global provider list.
provider p = new provider(t);
t_info.provider_list.Add(p);
//Null out the segments of the current transaction
//We are done with them and now the garbage collector
//can clean them up for us.
t.segments = null;
}));
}
Task.WaitAll(tasks.ToArray());
foreach(provider p in t_info.providers){
//Every provider has a List<claims> claims_list
//Do something with p.claims_list
foreach(claim c in p.claims_list){ //<--null exception here
}
}
t_info.provider_list
是一个List<provider>
类,如果同时有多个线程对其进行写操作,该类是不安全的,你必须同步访问列表
lock(t_info.provider_list)
{
t_info.provider_list.Add(p);
}
这将只允许单个线程一次执行Add调用,并将解决您的问题与破碎的集合
让这个更容易得到正确的建议:使用Task.WhenAll
代替。使每个任务返回一个值,该值是它自己的工作单元的结果。
WhenAll
具有签名:
Task<TResult[]> WhenAll<TResult>(IEnumerable<Task<TResult>> tasks)
任务。
MSDN上的WhenAll所以你传递给它一个任务的集合,每个任务的计算值都是一个TResult
,然后你得到一个任务,它的计算值是一个包含所有结果的数组。
这样,你就免除了使用线程安全集合在任务之间传递数据的责任。更不容易出错。
它也兼容async
/await
,这都是关于消费通过任务返回的值。