【问题标题】:Task.WaitAll(tasks.ToArray()); Freezes [duplicate]Task.WaitAll(tasks.ToArray());冻结[重复]
【发布时间】:2017-12-31 08:17:29
【问题描述】:

我将重新表述这个问题。这是我想做的简化代码。 标签 将是动态的,并且必须在函数中传递。函数startCount() 会做更多的事情,我想把每一个都删掉以节省时间。代码工作正常(现在计算并更改值)。
当所有任务完成后,我还需要执行其他功能。
我在startCount()函数中取出了多余的Task

至于其他示例,我没有使用 await 并且在 startCount() 中删除了 Task 现在程序冻结了。

private void Form1_Load(object sender, EventArgs e)
{
    strCounter.Add("66");   //Simulate reading file 
    strCounter.Add("69");

    labels = new Label[strCounter.Count];   //Create the Array of Labels

    for (int i = 0; i < strCounter.Count; i++)
    {
        labels[i] = new Label();            //Create label and add it to Form
        labels[i].Size = new Size(30, 15);
        labels[i].Location = new Point(10, 50 + (i * 20));
        labels[i].Text = strCounter[i];
        this.Controls.Add(labels[i]);
    }
}

private void button1_Click(object sender, EventArgs e)
{
    List<Task> tasks = new List<Task>();    //Create List of Tasks

    for (int i = 0; i < strCounter.Count; i++)
    {
        int ii = i;
        Task LastTask = new Task(() => startCount(i.ToString(), labels[ii]));

        tasks.Add(LastTask);
        tasks[i].ConfigureAwait(false);
        tasks[i].Start();

    }
    // This line will cause the entire program to freeze.
    // If i comment out, the program works fine.
    Task.WaitAll(tasks.ToArray());

    MessageBox.Show("Should be After");
}

private void startCount(string strCount, Label lbl)
{
    for (int i = 0; i < 100; i++)
    {
        int count = int.Parse(lbl.Text) + 1;    //Add 1
        writeLabelBox(lbl, count.ToString());   //Use Invoke function
        Thread.Sleep(20);
    }
}

public void writeLabelBox(Label l, string strA)
{
    this.Invoke((MethodInvoker)delegate()
    {
        l.Text = strA;
    });
}

【问题讨论】:

  • 可能所有任务都完成了?
  • 这太可怕了,你无缘无故地创建任务。你会饿死线程池。
  • 您不需要做new TaskTask.Start()。这些是您不使用的高级功能所必需的,并且会使事情复杂化。请改用Task.Run()。还有@ErikPhilips 所说的——你在太细粒度的水平上并行化事情,它会变得更慢。因此,如果它是一款真正的应用,请重新考虑您的策略。
  • 你的代码有很多问题,但主要是你已经将你真正想要等待的任务包装在一个立即完成的不同任务中,因为不同的任务是无非是创建您真正想要等待的任务(当然,这需要很少的时间)。查看 Stack Overflow 上数千个或更多类似问题的标记重复项,我们已经回答了这些问题。
  • 我真的将代码简化为它真正要做的事情。该标签是众多标签中的一部分,并且不希望为该问题添加额外代码。是的,我确实想解决这个问题。该线程将为 UI 提供更新时间,如果我注释掉 Task.WaitAll(tasks.ToArray());.,它可以正常工作

标签: c# arrays task wait


【解决方案1】:

您已经在函数内部创建了一个任务并返回它。 所以你不需要创建另一个任务。
你只是在等待错误的任务。

改变这一行:

Task LastTask = new Task(() => startCount(i.ToString(), labels[ii]));

到这里:

Task LastTask = startCount(i.ToString(), labels[ii]);

并删除tasks[i].Start();,因为它已经在函数中启动。

或者保持原样,但不要在函数中创建Task

无论如何,为什么要为每个标签创建一个任务,而不是为整个循环创建一个任务?

【讨论】:

  • 还有一点:.ConfigureAwait(false) 如果可能的话。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2021-01-23
  • 2016-02-29
  • 2019-02-04
  • 1970-01-01
相关资源
最近更新 更多