如何在 C# 中 运行 并发任务
how to run concurrent tasks in c#
我编写了一个控制台应用程序来处理图像文件并将它们与数据库记录进行匹配。
图像文件都位于不同文件夹的文件存储中,每天一个文件夹,因此文件存储的结构是
<code>FileStore -> Day1 -> Images
-------------------> Indexfile.csv
所以我的程序将打开每个文件夹获取索引文件并将图像与数据库中的记录匹配。
文件夹很大,其中一些有 90000 多张图片,所以我想 运行 最多 5 个不同的任务,每个任务抓取一个不同的文件夹并并行处理它们,我尝试创建 5 个tasks 并且工作正常,除了我不知道如何在 5 个任务中的一个完成后开始新任务。
任何指点将不胜感激。
谢谢。
最简单的方法是创建一个包含所有文件的列表并使用 Parallel.ForEach
,查看文档 https://msdn.microsoft.com/en-us/library/dd460720%28v=vs.110%29.aspx?f=255&MSPPError=-2147217396
示例代码:
// A simple source for demonstration purposes. Modify this path as necessary.
String[] files = System.IO.Directory.GetFiles(@"C:\Users\Public\Pictures\Sample Pictures", "*.jpg");
String newDir = @"C:\Users\Public\Pictures\Sample Pictures\Modified";
System.IO.Directory.CreateDirectory(newDir);
// Method signature: Parallel.ForEach(IEnumerable<TSource> source, Action<TSource> body)
// Be sure to add a reference to System.Drawing.dll.
Parallel.ForEach(files, (currentFile) =>
{
// The more computational work you do here, the greater
// the speedup compared to a sequential foreach loop.
String filename = System.IO.Path.GetFileName(currentFile);
var bitmap = new Bitmap(currentFile);
bitmap.RotateFlip(RotateFlipType.Rotate180FlipNone);
bitmap.Save(Path.Combine(newDir, filename));
// Peek behind the scenes to see how work is parallelized.
// But be aware: Thread contention for the Console slows down parallel loops!!!
Console.WriteLine("Processing {0} on thread {1}", filename, Thread.CurrentThread.ManagedThreadId);
//close lambda expression and method invocation
});
// Keep the console window open in debug mode.
Console.WriteLine("Processing complete. Press any key to exit.");
Console.ReadKey();
您应该在任务列表中使用WhenAny
(非阻塞)或WaitAny
(阻塞)。然后从列表中删除任何已完成的任务并添加新任务。
List<Task<...>> tasks = ... // put your 5 tasks inside this list.
while(condintion)
{
await Task.WhenAny(tasks);
tasks.RemoveAll(t => t.IsCompleted);
while(tasks.Count < 5 && condintion)
{
Task<...> newTask = ... // run your task
tasks.Add(newTask);
}
}
设置适当的条件,以便只有在所有文件夹都被占用时才为 false。
我编写了一个控制台应用程序来处理图像文件并将它们与数据库记录进行匹配。
图像文件都位于不同文件夹的文件存储中,每天一个文件夹,因此文件存储的结构是
<code>FileStore -> Day1 -> Images
-------------------> Indexfile.csv
所以我的程序将打开每个文件夹获取索引文件并将图像与数据库中的记录匹配。
文件夹很大,其中一些有 90000 多张图片,所以我想 运行 最多 5 个不同的任务,每个任务抓取一个不同的文件夹并并行处理它们,我尝试创建 5 个tasks 并且工作正常,除了我不知道如何在 5 个任务中的一个完成后开始新任务。
任何指点将不胜感激。
谢谢。
最简单的方法是创建一个包含所有文件的列表并使用 Parallel.ForEach
,查看文档 https://msdn.microsoft.com/en-us/library/dd460720%28v=vs.110%29.aspx?f=255&MSPPError=-2147217396
示例代码:
// A simple source for demonstration purposes. Modify this path as necessary.
String[] files = System.IO.Directory.GetFiles(@"C:\Users\Public\Pictures\Sample Pictures", "*.jpg");
String newDir = @"C:\Users\Public\Pictures\Sample Pictures\Modified";
System.IO.Directory.CreateDirectory(newDir);
// Method signature: Parallel.ForEach(IEnumerable<TSource> source, Action<TSource> body)
// Be sure to add a reference to System.Drawing.dll.
Parallel.ForEach(files, (currentFile) =>
{
// The more computational work you do here, the greater
// the speedup compared to a sequential foreach loop.
String filename = System.IO.Path.GetFileName(currentFile);
var bitmap = new Bitmap(currentFile);
bitmap.RotateFlip(RotateFlipType.Rotate180FlipNone);
bitmap.Save(Path.Combine(newDir, filename));
// Peek behind the scenes to see how work is parallelized.
// But be aware: Thread contention for the Console slows down parallel loops!!!
Console.WriteLine("Processing {0} on thread {1}", filename, Thread.CurrentThread.ManagedThreadId);
//close lambda expression and method invocation
});
// Keep the console window open in debug mode.
Console.WriteLine("Processing complete. Press any key to exit.");
Console.ReadKey();
您应该在任务列表中使用WhenAny
(非阻塞)或WaitAny
(阻塞)。然后从列表中删除任何已完成的任务并添加新任务。
List<Task<...>> tasks = ... // put your 5 tasks inside this list.
while(condintion)
{
await Task.WhenAny(tasks);
tasks.RemoveAll(t => t.IsCompleted);
while(tasks.Count < 5 && condintion)
{
Task<...> newTask = ... // run your task
tasks.Add(newTask);
}
}
设置适当的条件,以便只有在所有文件夹都被占用时才为 false。