确保主线程等待所有任务完成

时间:2012-11-14 19:00:39

标签: c# multithreading task-parallel-library task

我正在编写一个C#控制台应用程序,并且遇到主要线程在所有生成的关闭任务都有机会完成之前关闭的问题。一般程序流程如下所示:

程序将目录的路径作为命令行参数。然后迭代该目录中与特定扩展名匹配的每个文件,并为每个匹配的文件生成一个新任务,以打开并分析该文件:

Directory.GetFiles(directoryPath).ToList<string>().Where(x => Path.GetExtension(x) == ".xfast").ToList().ForEach(x => ProcessXFastFile(x));

这些文件中的每一个都包含大量CSV值,这些值对应于唯一的产品密钥。例如,一个文件可能包含100万个CSV行和400个唯一的产品密钥。该程序的目的是根据产品密钥对所有行进行排序,并根据密钥将其写回单个文件。

因此,在ProcessXFastFile方法中,我使用产品代码作为键值创建Dictionary<string, List<string>>,并将与该键匹配的每个CSV行添加到相应的列表中。

排序完成后,我遍历字典并为每个Key值生成一个新任务,并在该List中写出CSV行:

foreach (KeyValuePair<string, List<string>> entry in productDictionary) {
    string writePath = String.Format(@"{0}\{1}-{2}.txt", directoryPath, hour, entry.Key);
    List<string> quotes = entry.Value;
    Task writeFileTask = Task.Factory.StartNew(() => WriteProductFile(writePath, quotes));
}

问题是主要线程在每个任务到WriteProductFile之前都有机会完成写出他们的数据。例如,我使用一个文件作为控制测试,并且知道字典中有~450个唯一键,因此应该写出许多相应的文件。但是,在程序结束之前,只有大约10个文件有机会写出来。

如何确保我的程序保持足够长的时间以完成所有任务?任何帮助表示赞赏。

1 个答案:

答案 0 :(得分:5)

您可以将获得的所有任务放入List<Task>,而不是仅创建它们并抛弃它们,然后使用Task.WaitAll()等待完成:

var tasks = new List<Task>();

foreach (KeyValuePair<string, List<string>> entry in productDictionary) {
    string writePath = String.Format(@"{0}\{1}-{2}.txt", directoryPath, hour, entry.Key);
    List<string> quotes = entry.Value;

    // add task to list
    tasks.Add(Task.Factory.StartNew(() => WriteProductFile(writePath, quotes)));
}

// now wait for all tasks to finish, you'd also want to handle  exceptions of course.
Task.WaitAll(tasks.ToArray());

WaitAll()有很多变体,你可以无限期地等待(如上所述),或者等待TimeSpan,如果超时,则打印进度消息并再次等待......