C# Task.WaitAll(tasks.ToArray());冻结

C# Task.WaitAll(tasks.ToArray());冻结,c#,arrays,task,wait,C#,Arrays,Task,Wait,我将重新措辞这个问题。这是我想做的一个简化代码。标签将是动态的,必须在函数中传递。函数startCount()将做更多的工作,为了节省时间,我想将每一个都线程化。代码工作正常(现在计算并更改值)。 完成所有任务后,我还需要执行其他功能。 我在startCount()函数中取出了额外的任务 至于其他示例,我没有使用await,在startCount()中删除ot任务,现在程序冻结 private void Form1_Load(object sender, EventArgs e) { s

我将重新措辞这个问题。这是我想做的一个简化代码。标签将是动态的,必须在函数中传递。函数
startCount()
将做更多的工作,为了节省时间,我想将每一个都线程化。代码工作正常(现在计算并更改值)。
完成所有任务后,我还需要执行其他功能。
我在
startCount()
函数中取出了额外的任务

至于其他示例,我没有使用
await
,在
startCount()
中删除ot任务,现在程序冻结

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;
    });
}
private void Form1\u加载(对象发送方,事件参数e)
{
strCounter.Add(“66”);//模拟读取文件
补充(“69”);
labels=新标签[strCounter.Count];//创建标签数组
for(int i=0;istartCount(i.ToString(),labels[ii]);
任务。添加(最后一个任务);
任务[i]。配置等待(false);
任务[i].Start();
}
//此行将导致整个程序冻结。
//如果我将其注释掉,程序运行良好。
Task.WaitAll(tasks.ToArray());
MessageBox.Show(“应该在后面”);
}
专用void startCount(字符串strCount,标签lbl)
{
对于(int i=0;i<100;i++)
{
int count=int.Parse(lbl.Text)+1;//添加1
writeLabelBox(lbl,count.ToString());//使用调用函数
睡眠(20);
}
}
公共空写标签盒(标签l,字符串strA)
{
this.Invoke((MethodInvoker)委托()
{
l、 Text=strA;
});
}

您已经在函数中创建了一个任务并返回了它。 因此,您不需要创建另一个任务。
你只是在等待错误的任务

更改此行:

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

Task LastTask = startCount(i.ToString(), labels[ii]);
并删除
任务[i].Start()因为它已在函数中启动

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


在任何情况下,为什么要为每个标签创建一个任务,而不是为整个循环创建一个任务?

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

更改此行:

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

Task LastTask = startCount(i.ToString(), labels[ii]);
并删除
任务[i].Start()因为它已在函数中启动

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


在任何情况下,为什么要为每个标签创建一个任务,而不是为整个循环创建一个任务?

可能所有任务都已完成?这太可怕了,您无缘无故地创建任务。您将耗尽线程池。您不需要执行
newtask
Task.Start()
。这些是您不使用的高级功能所必需的,并且会使事情变得复杂。改用
Task.Run()
。还有@ErikPhilips所说的——你把事情并行化的粒度太细了,速度会变慢。因此,如果它是一个真正的应用程序,请重新考虑你的策略。你的代码有很多错误,但最主要的是你已经将你真正想等待的任务包装在一个立即完成的不同任务中,因为不同的任务只不过是创建你真正想等待的任务(当然,这只需要很少的时间)。关于堆栈溢出,我们已经回答了数千个或更多类似问题,请参见标记的重复项。我确实将代码简化为它真正要做的事情。标签是许多问题中的一部分,不需要额外的代码来解决问题。是的,我确实希望解决这个问题。线程将给UI时间to更新,如果我注释掉Task.WaitAll(tasks.ToArray());,它可以正常工作。可能所有任务都已完成?这太可怕了,您无缘无故创建任务。您将耗尽线程池。您不需要执行
新建任务
任务.Start()
。这些是您不使用的高级功能所必需的,并且会使事情变得复杂。请使用
Task.Run()
相反。正如@ErikPhilips所说的,你将事情并行化的粒度太细,速度会变慢。因此,如果它是一个真正的应用程序,请重新考虑你的策略。你的代码有很多错误,但最主要的是你已经将你真正想等待的任务包装在一个立即完成的不同任务中,bec因为不同的任务只不过是创建您真正想要等待的任务(当然,这只需要很少的时间)。关于堆栈溢出,我们已经回答了数千个或更多类似问题,请参见标记的重复项。我确实将代码简化为它真正要做的事情。标签是许多问题中的一部分,不需要额外的代码来解决问题。是的,我确实希望解决这个问题。线程将给UI时间to更新,如果我注释掉Task.WaitAll(tasks.ToArray());,它可以正常工作。还有一件事:
.ConfigureAwait(false)
(如果可能)。还有一件事:
.ConfigureAwait(false)
(如果可能)。