它同时显示其中两个的原因与您如何链接待命有关。
listBox1.Items.Add(await longTask);
listBox1.Items.Add(await shortTask);
您正在等待较短的任务,然后再等待较短的任务。第二行是在较长的任务完成工作之后运行的,而这又是较短的时间,这就是为什么您同时看到它们的原因。但是在现实世界中,您不知道执行什么任务将需要更长的时间,您需要一个更好的解决方案。
Action<Task<string>> continuationFunction = t => { this.listBox1.Items.Add(t.Result); };
Task.Run(() => LongTaskAsync()).ContinueWith(continuationFunction,TaskScheduler.FromCurrentSynchronizationContext());
Task.Run(() => ShortTaskAsync()).ContinueWith(continuationFunction,TaskScheduler.FromCurrentSynchronizationContext());
TaskScheduler.FromCurrentSynchronizationContext()
用于避免跨线程访问异常。
,
您不必为此使用ContinueWith
。几乎总是可以避免混合async/await
和ContinueWith
风格的延续。就您而言,可以这样完成:
async void BtnRunClick(object sender,EventArgs e)
{
listBox1.Items.Clear();
async Task longTaskHelperAsync() {
// probably,Task.Run is redundant here,// could just do: var item = await LongTaskAsync();
var item = await Task.Run(() => LongTaskAsync());
listBox1.Items.Add(item);
}
async Task shortTaskHelperAsync() {
// probably,too
var item = await Task.Run(() => ShortTaskAsync());
listBox1.Items.Add(item);
}
await Task.WhenAll(longTaskHelperAsync(),shortTaskHelperAsync());
}
我相信这种方式更具可读性,您不必担心同步上下文,FromCurrentSynchronizationContext
等。
另外,如果在那些异步ctask仍在运行中的情况下再次单击BtnRunClick
,则很可能需要重新输入。
,
您可以通过创建一种等待任务的方法,并将该任务的结果添加到ListBox
中,来更一般地解决该问题。
async Task ProcessAndAddToListAsync(Func<Task<string>> function)
{
var value = await Task.Run(function); // Start the task in a background thread
listBox1.Items.Add(value); // Update the control in the UI thread
}
然后在按钮单击事件的事件处理程序中使用此方法:
async void BtnRunClick(object sender,EventArgs e)
{
listBox1.Items.Clear();
var longTask = ProcessAndAddToListAsync(LongTaskAsync);
var shortTask = ProcessAndAddToListAsync(ShortTaskAsync);
await Task.WhenAll(longTask,shortTask); // optional
// Here do anything that depends on both tasks being completed
}
本文链接:https://www.f2er.com/3090588.html