为什么是任务?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
              }
        }

为什么是任务?WaitAll不等待所有任务完成?c#

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,这都是关于消费通过任务返回的值。