【问题标题】:how to run concurrent tasks in c#如何在c#中运行并发任务
【发布时间】:2015-12-16 18:32:13
【问题描述】:

我编写了一个控制台应用程序来处理图像文件并将它们与数据库记录匹配。

图像文件都位于不同文件夹的文件存储中,每天一个文件夹,因此文件存储的结构将是

FileStore -> Day1 -> Images -------------------> Indexfile.csv

所以我的程序将打开每个文件夹抓取索引文件并将图像与数据库中的记录匹配。

这些文件夹非常大,其中一些有 90000 多张图像,所以我想运行多达 5 个不同的任务,每个任务抓取一个不同的文件夹并并行处理它们,我尝试创建 5 个任务并且工作正常,除了5 个任务之一完成后,我不知道如何开始新任务。

任何指针将不胜感激。

谢谢。

【问题讨论】:

  • 我投票决定将此问题作为题外话结束,因为您需要自己阅读文档,首先努力并提出具体问题。
  • 或者,显示一些您怀疑的实际代码。
  • 这对于 Stack Overflow 来说是相当广泛的。但是 - 所有这些文件夹都在同一个物理磁盘上吗?如果是这样,您一次不可能读取多个文件夹,并且如果处理主要是磁盘绑定,那么运行并行任务就没有什么意义了。
  • 谁能说我没有付出努力......提供的两个答案给了我解决方案......
  • 请确保您在发布代码时附上您的问题。如果您有minimal reproducible example,那么我们可以轻松回答。

标签: c# task


【解决方案1】:

简单的方法是创建一个包含所有文件的列表并使用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();

【讨论】:

  • @franklores 你不能,但你可以upvote 任意数量
【解决方案2】:

您应该在任务列表中使用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);
    }
}

设置适当的条件,这样只有在所有文件夹都被占用时才为假。

【讨论】:

  • 请注意,这只是一般的想法。你需要根据你的需要修改它;)@franklores
猜你喜欢
  • 2015-08-23
  • 1970-01-01
  • 2016-02-28
  • 1970-01-01
  • 1970-01-01
  • 2018-11-28
  • 2023-01-27
  • 2010-11-03
  • 2021-12-02
相关资源
最近更新 更多