【问题标题】:Task Wait in For Loop C#For循环C#中的任务等待
【发布时间】:2020-05-26 09:06:19
【问题描述】:

我正在读取一个文件,想一次处理 10 行。

这仅在我处理

请指教。

下面是我的代码:

private void btnStart_Click(object sender, EventArgs e)
{
  int lctr = 0;
  var tasks = new List<Task>();
  foreach (string s in lines)
  {
    if (string.IsNullOrWhiteSpace(s) || string.IsNullOrEmpty(s))
      continue;

    lctr++;
    tasks = new List<Task>();
    if (lctr < 11)
    {
      Console.WriteLine(lctr + " - " + s);
      tasks.Add(Task.Factory.StartNew(() => processThis(s)));
    }
    else
    {                        
    Console.WriteLine("Waiting ...");
    Task.WaitAll(tasks.ToArray());
    }
  }
  if (tasks.Count > 0)
    Task.WaitAll(tasks.ToArray());        
 }

【问题讨论】:

  • tasks 在您对其进行WaitAll 时将始终为空,因为您在if 之前为它重新分配了一个空列表。
  • 此外,您还需要在每批 10 个之后重置 lctr,否则您将永远不会再次进入 lctr &lt; 11 条件。
  • 你为什么要在这里使用任务?没有任何异步发生。 processThis 是异步的吗?
  • 你到底想做什么?并行处理一批 10 个项目?为什么要在批次之间等待?
  • 两个问题:您正在为每个 linge 重置任务,并且您没有每 10 行将 lctr 设置为零。

标签: c# asynchronous foreach task wait


【解决方案1】:

当您说“请提供建议”时,它给了我很大的尝试和帮助的余地。以下是我的建议,希望您觉得它们“有用”:

问:“我正在读取一个文件,想一次处理 10 行。”

答:在生成任何任务之前,将您的测试列表放入 10 个字符串的组中(如果列表长度为 25 个字符串,则最后一组可能是部分的)。

这是第一部分的方法:

    // Short-running method that queues up strings in batches of 10 or less
    private static Queue<List<string>> enqueueBatchesOf10orLess(List<string> testData)
    {
        Queue<List<string>> batchesOfUpTo10 = new Queue<List<string>>();
        List<string> singleBatchOfUpTo10 = new List<string>(); ;
        for (int count = 0; count < testData.Count; count++)
        {
            if ((count % 10) == 0) 
            {
                if(count != 0)  // Skip the very first time
                {
                    batchesOfUpTo10.Enqueue(singleBatchOfUpTo10);
                    singleBatchOfUpTo10 = new List<string>();
                }
            }
            singleBatchOfUpTo10.Add(testData[count]);
        }
        // Leftover batch of less-than-10
        if(singleBatchOfUpTo10.Count != 0)
        {
            batchesOfUpTo10.Enqueue(singleBatchOfUpTo10);
        }
        return batchesOfUpTo10;
    }

接下来,您似乎希望同时处理这些批次(这意味着可能需要一些处理时间来证明这样做是合理的)。以下是您传递“10 批或更少批次”并获得任务作为回报的方法。

    private static Task processBatch(Queue<List<string>> batches)
    {            
        return Task.Run(() => // Return task that processes batch of 10 or less
        {
            var batch = batches.Dequeue();
            foreach (var singleString in batch)
            {
                processThis(singleString);
            }
        });
    }

...哪里...

    private static void processThis(string s)
    {
        Task.Delay(100).Wait(); // Simulate long-running string processing
        Console.WriteLine(s);
    }

测试一下:

    static void Main(string[] args)
    {
        // Make some test data
        List<string> testData = new List<string>();
        for (int i = 0; i < 25; i++) testData.Add((i + 1).ToString());

        Queue<List<string>> batchesOf10OrLess = enqueueBatchesOf10orLess(testData);

        List<Task> tasks = new List<Task>();
        for (int i = 0; i < batchesOf10OrLess.Count; i++)
        {
            // Pass in the queue of batches and get a Task in return.
            tasks.Add(processBatch(batchesOf10OrLess));
        }
        Console.WriteLine("The test data is NOT in order.");
        Console.WriteLine("This is proof the tasks are running concurrently");
        Task.WaitAll(tasks.ToArray());

        // Pause
        Console.ReadKey();
    }

这是我们得到的:

The test data is NOT in order.
This is proof the tasks are running concurrently
1
21
11
2
12
22
3
23
13
4
14
24
5
25
15
6
16
7
17
8
18
19
9
10
20

如果你喜欢 download 这个来自 GitHub 的示例。

【讨论】:

  • 感谢您的时间和建议,我会在几天后尝试一下,因为我会离线。
猜你喜欢
  • 2023-01-20
  • 2021-03-15
  • 2018-06-09
  • 2018-01-06
  • 1970-01-01
  • 2012-12-09
  • 2023-04-11
相关资源
最近更新 更多