为什么Task.Wait会等到我的所有任务完成之后才等到? C#

时间:2016-09-01 19:18:23

标签: c# multithreading asynchronous

在我开始之前。我看过类似的问题,但我认为他们没有答案。

我遇到Task.Factory.StartNew和Task.WaitAll的问题。

我在任务中初始化的已创建类中的对象上获得null异常,即使抛出空异常的代码应该等待所有任务完成。

如果我在没有任务的情况下运行此代码,它可以正常工作。

为什么Task.Wait会等到所有任务都完成后才等待?

        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

              }
        }

2 个答案:

答案 0 :(得分:1)

t_info.provider_listList<provider>这个类一次有多个线程写入它是不安全的,你必须同步访问列表。

lock(t_info.provider_list)
{
    t_info.provider_list.Add(p);
}

这样只允许一个线程一次执行Add调用,并将修复您的问题。

答案 1 :(得分:1)

建议您更容易做到:使用"li"代替。使每个任务返回一个值,该值是其自身工作单元的结果。

Task.WhenAll有签名:

WhenAll

Task.WhenAll on MSDN

因此,您将每个评估为Task<TResult[]> WhenAll<TResult>(IEnumerable<Task<TResult>> tasks) 的任务集合传递给它,然后您将返回一个任务,该任务在完成后会计算出包含所有结果的数组。

这样,您就免除了使用线程安全集合在任务之间传递数据的任何责任。错误要困难得多。

它还与TResult / async兼容,这与消耗通过任务返回的值有关。