WhenAll() 没有按预期工作
WhenAll() not working as expected
我需要让 UI 线程等待任务数组完成 execution.The 以下代码的问题是 - 任务依次调用 UI 线程写入文本框。如何解决这个问题?
public partial class FormConsole : Form
{
public FormConsole()
{
InitializeComponent();
}
void txtSayHello_Click(object sender, EventArgs e)
{
Class1 objclss = new Class1();
objclss.formConsole = this;
Task[] taa = new Task[4];
taa[0] = new Task(() => objclss.DoSomeThigs("Hello world"));
taa[1] = new Task(() => objclss.DoSomeThigs("Hello world1"));
taa[2] = new Task(() => objclss.DoSomeThigs("Hello world2"));
taa[3] = new Task(() => objclss.DoSomeThigs("Hello world3"));
foreach(Task task in taa)
{
task.Start();
}
Task.WhenAll(taa);
this.txtConsole.AppendText("All threads complete");
}
delegate void doStuffDelegate(string value);
public void doStuff(string value)
{
if (System.Windows.Forms.Form.ActiveForm.InvokeRequired && IsHandleCreated)
{
BeginInvoke(new doStuffDelegate(doStuff), value);
}
else
txtConsole.AppendText(value);
}
}
public class Class1
{
public FormConsole formConsole;
public void DoSomeThigs(string sampleText)
{
formConsole.doStuff(sampleText);
}
}
o/p 现在:Console Redirection TestAll threads completeHello worldHello world1Hello world2Hello world3
o/p 我要:Console Redirection TestHello worldHello world1Hello world2Hello world3All threads complete
有什么解决办法?
Task.WhenAll
returns 当所有传递给它的任务完成时完成的任务。您必须 await
此任务,否则该方法将继续执行。
async void txtSayHello_Click(object sender, EventArgs e)
{
...
await Task.WhenAll(taa);
...
}
此方法有一个阻塞版本 - Task.WaitAll
。它将阻塞当前线程,直到所有任务完成,但阻塞 UI 线程并不是一个好主意。
此外,在线程池线程上启动任务的首选方法是使用 Task.Run
。
Task.WhenAll
returns一个Task
代表枚举中所有这些任务的完成。您需要等待该任务,因为该方法不会阻塞线程。
将 txtSayHello_Click
转换为 async void
(应该仅用于事件处理程序)方法并等待从 Task.WhenAll
:
返回的任务
async void txtSayHello_Click(object sender, EventArgs e)
{
// ...
await Task.WhenAll(taa);
// ...
}
此外,您应该几乎总是避免使用 Task
构造函数。如果您需要 UI 线程上的 运行 任务(这取决于您对 FormConsole
的实际操作)或 Task.Run
如果你不这样做。含义:
taa[0] = Task.Factory.StartNew(() => objclss.DoSomeThigs("Hello world"), CancellationToken.None, TaskCreationOptions.None,
TaskScheduler.FromCurrentSynchronizationContext());
或者:
taa[0] = Task.Run(() => objclss.DoSomeThigs("Hello world"));
您很可能将 WhenAll()
与 WaitAll()
混淆了。
正如已经建议的那样,您可以将 async
与 await
一起使用,或者您可以简单地使用 :
A) Task.WhenAll(taa).Wait();
B) Task.WaitAll(taa);
但在您的情况下,这将阻塞 UI 线程。因此,最好将其余代码放入 Continuation Task 并使用 Control.Invoke()
调用 UI 操作:
Task.WhenAll(taa).ContinueWith(t =>
{
this.Invoke(() => this.txtConsole.AppendText("All threads complete"));
});
我需要让 UI 线程等待任务数组完成 execution.The 以下代码的问题是 - 任务依次调用 UI 线程写入文本框。如何解决这个问题?
public partial class FormConsole : Form
{
public FormConsole()
{
InitializeComponent();
}
void txtSayHello_Click(object sender, EventArgs e)
{
Class1 objclss = new Class1();
objclss.formConsole = this;
Task[] taa = new Task[4];
taa[0] = new Task(() => objclss.DoSomeThigs("Hello world"));
taa[1] = new Task(() => objclss.DoSomeThigs("Hello world1"));
taa[2] = new Task(() => objclss.DoSomeThigs("Hello world2"));
taa[3] = new Task(() => objclss.DoSomeThigs("Hello world3"));
foreach(Task task in taa)
{
task.Start();
}
Task.WhenAll(taa);
this.txtConsole.AppendText("All threads complete");
}
delegate void doStuffDelegate(string value);
public void doStuff(string value)
{
if (System.Windows.Forms.Form.ActiveForm.InvokeRequired && IsHandleCreated)
{
BeginInvoke(new doStuffDelegate(doStuff), value);
}
else
txtConsole.AppendText(value);
}
}
public class Class1
{
public FormConsole formConsole;
public void DoSomeThigs(string sampleText)
{
formConsole.doStuff(sampleText);
}
}
o/p 现在:Console Redirection TestAll threads completeHello worldHello world1Hello world2Hello world3
o/p 我要:Console Redirection TestHello worldHello world1Hello world2Hello world3All threads complete
有什么解决办法?
Task.WhenAll
returns 当所有传递给它的任务完成时完成的任务。您必须 await
此任务,否则该方法将继续执行。
async void txtSayHello_Click(object sender, EventArgs e)
{
...
await Task.WhenAll(taa);
...
}
此方法有一个阻塞版本 - Task.WaitAll
。它将阻塞当前线程,直到所有任务完成,但阻塞 UI 线程并不是一个好主意。
此外,在线程池线程上启动任务的首选方法是使用 Task.Run
。
Task.WhenAll
returns一个Task
代表枚举中所有这些任务的完成。您需要等待该任务,因为该方法不会阻塞线程。
将 txtSayHello_Click
转换为 async void
(应该仅用于事件处理程序)方法并等待从 Task.WhenAll
:
async void txtSayHello_Click(object sender, EventArgs e)
{
// ...
await Task.WhenAll(taa);
// ...
}
此外,您应该几乎总是避免使用 Task
构造函数。如果您需要 UI 线程上的 运行 任务(这取决于您对 FormConsole
的实际操作)或 Task.Run
如果你不这样做。含义:
taa[0] = Task.Factory.StartNew(() => objclss.DoSomeThigs("Hello world"), CancellationToken.None, TaskCreationOptions.None,
TaskScheduler.FromCurrentSynchronizationContext());
或者:
taa[0] = Task.Run(() => objclss.DoSomeThigs("Hello world"));
您很可能将 WhenAll()
与 WaitAll()
混淆了。
正如已经建议的那样,您可以将 async
与 await
一起使用,或者您可以简单地使用 :
A) Task.WhenAll(taa).Wait();
B) Task.WaitAll(taa);
但在您的情况下,这将阻塞 UI 线程。因此,最好将其余代码放入 Continuation Task 并使用 Control.Invoke()
调用 UI 操作:
Task.WhenAll(taa).ContinueWith(t =>
{
this.Invoke(() => this.txtConsole.AppendText("All threads complete"));
});