问题描述
我正在编写一个C#控制台应用程序,并且遇到一个问题,即在所有产生的Tasks有机会完成之前,主线程已关闭.常规程序流程如下:
I'm writing a C# console app and having an issue where the primary thread closes before all the spawned off Tasks have a chance to complete. General program flow looks like this:
程序将目录路径作为命令行参数.然后,它将遍历该目录中与特定扩展名匹配的每个文件,并为每个匹配文件产生一个新任务以打开并分析该文件:
The program takes the path to a directory as a command line parameter. It then iterates over every file in that directory matching a specific extension and spawns a new task for each matching file to open up and analyze that file:
Directory.GetFiles(directoryPath).ToList<string>().Where(x => Path.GetExtension(x) == ".xfast").ToList().ForEach(x => ProcessXFastFile(x));
每个文件都包含大量CSV值,它们对应于唯一的产品密钥.例如,一个文件可能包含一百万条CSV行和400个唯一的产品密钥.该程序的重点是根据产品密钥对所有行进行排序,然后根据密钥将它们写回到单独的文件中.
Each of these files contains a large number of CSV values corresponding back to a unique product key. For example, one file might contain 1 million CSV lines and 400 unique product keys. The point of the program is to sort all of the lines based on the product key and write them back out to individual files based on the key.
因此,在ProcessXFastFile方法中,我使用产品代码作为键值创建一个Dictionary<string, List<string>>
,并将与该键匹配的每个CSV行添加到相应的列表中.
So in the ProcessXFastFile method I create a Dictionary<string, List<string>>
using the product codes as Key values and adding each CSV line that matches that key into the corresponding list.
排序完成后,我遍历字典并为每个键值产生一个新任务,并在该列表中写出CSV行:
Once the sorting is finished, I iterate over the dictionary and spawn off a new task for each Key value and write out the CSV lines in that List:
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个文件有机会在程序结束之前写出.
The problem is that the primary thread is ending before each of these Tasks to WriteProductFile have a chance to finish writing out their data. For example, I use one file as a control test and know that at there are ~450 unique keys in the dictionary so there should be that many corresponding files written out. However, only about 10 files get a chance to write out before the program ends.
如何确保我的程序的生存时间足够长,以完成所有任务?感谢您的帮助.
How can I ensure that my program stays live long enough for all Tasks to finish? Any help is appreciated.
推荐答案
您可以将获得的所有任务放入List<Task>
中,而不仅仅是创建并扔掉它们,然后使用Task.WaitAll()
等待完成:
You can put all of the tasks you get into a List<Task>
instead of just creating them and tossing them, and then use the Task.WaitAll()
to wait for completion:
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
,如果超时则打印进度消息,然后再次等待,等等.
There are many variations of WaitAll()
, you could wait indefinitely (as above), or wait for a TimeSpan
and if time-out then print a progress message and wait again, etc...
这篇关于确保主线程等待所有任务完成的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持!