gpt4 book ai didi

c# - Task.WaitAll() 没有按预期工作

转载 作者:太空狗 更新时间:2023-10-29 20:46:41 25 4
gpt4 key购买 nike

我正在尝试弄清楚如何使用 Task 类。过去我一直使用常规的 Thread 类,但我试图掌握所有异步编程...

例如,我创建了一个包含所有代码的主 Winforms 应用程序。我的问题的相关代码是:

//Relevant delegates
public delegate void MethodAction(int num);
public delegate void MethodConversion();
public delegate void OnCompletionAction(string completiontext);

//Button user presses
private void button4_Click(object sender, EventArgs e)
{
richTextBox1.Clear();
sw.Reset();
sw.Start();
Sync.RunAsync3(calcSim);
}

//The method that simulates a calculation by adding a sleep
//the input param threadlength is just to allow threads to take longer than others
//since I'm multithreading, I have to invoke the writing code on the windows RichTextbox control
private void calcSim(int threadlength)
{
string threadname = Thread.CurrentThread.Name;
for (int i = 0; i < 10; i++) //Thread calc should take 3s
{
Thread.Sleep(300 + threadlength);
richTextBox1.Invoke((MethodConversion)(() =>
{
richTextBox1.AppendText(string.Format("Thread: {0}\tVersion: {1}\n", threadname, (i + 1).ToString()));
}));
}
}

//Class that contains the different processing methods
public static class Sync
{
public static event OnCompletionAction OnProcCompletion;

public static void RunAsync3(MethodAction doM)
{
Task[] t = new Task[4];
for(int i = 0; i < 4; i++)
{
t[i] = Task.Factory.StartNew((Action)(() => { doM(50 * i); }));
}
Task.WaitAll(t);
if (OnProcCompletion != null) OnProcCompletion("RunSync method finished");
}
}

问题出在 Task.WaitAll(t)... 由于某种我无法弄清楚的原因,它完全阻塞在那条线上并且不再响应。如果我省略该行,表单会实时更新,执行大约需要 3 秒。

我的问题是:为什么 Task.WaitAll() 不在释放 UI 线程并允许其余代码执行之前阻塞 UI 线程 3 秒?

我知道它应该会阻塞 UI 一段时间(直到计算完所有线程),但它会无休止地阻塞整个应用程序。好像要等到永远?

编辑

有人建议我使用 WhenAll 而不是 WaitAll。我重写了 RunAsync3 如下:

public static void RunAsync3(MethodAction doM)
{
Task[] t = new Task[4];
for(int i = 0; i < 4; i++)
{
t[i] = Task.Factory.StartNew((Action)(() => { doM(50 * i); }));
}
//Task.WaitAll(t); -> deadlock
Task.WaitAll(new Task [] { Task.WhenAll(t) });
if (OnProcCompletion != null) OnProcCompletion("RunSync method finished");
}

但这仍然陷入僵局......?我可能没有正确使用 WhenAll?

编辑 2

因为每个人都声称我阻塞了 UI 线程是正确的,所以我决定尝试另一种方式:通过在 UI 线程内运行一个新线程作为我的调用线程(这样阻塞现在会发生在我的线程上而不是 UI线)。这行得通,但显然不是最好的方法!

private void button4_Click(object sender, EventArgs e)
{
Thread t = new Thread(new ThreadStart(() =>
{
richTextBox1.Invoke((MethodConversion)(() => richTextBox1.Clear()));
sw.Reset();
sw.Start();
Sync.RunAsync3(calcSim);
}));
t.Start();
}
public static void RunAsync3(MethodAction doM)
{
Task[] t = new Task[4];
for(int i = 0; i < 4; i++)
{
t[i] = Task.Factory.StartNew((Action)(() => { doM(50 * i); }));
}
Task.WaitAll(t);
//Task.WaitAll(new Task [] { Task.WhenAll(t) });
if (OnProcCompletion != null) OnProcCompletion("RunSync method finished");
}

最佳答案

你造成了僵局。

UI 线程正在等待 4 个任务完成。

另一方面,这 4 个运行 calcSim 的任务正在尝试调用 UI 线程上的代码 -> 死锁。

您应该改用 Task.WhenAll()。该方法将返回一个新任务,当您的所有任务完成后,该任务将被标记为已完成。如果您等待该任务,您的 UI 线程将被释放,因此 calcSim 将能够在 UI 线程上调用代码,避免死锁。

更新

你用错了。您仍在使用 WaitAll,这是一个阻塞调用。您应该将其替换WhenAll

await Task.WhenAll(t);

来自documentation :

Creates a task that will complete when all of the supplied tasks have completed.

通过对结果调用 await,您的 UI 线程将空闲 - 直到所有 4 个任务完成。发生这种情况时,您的 RunAsync3 方法将恢复。

关于c# - Task.WaitAll() 没有按预期工作,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/19766535/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com