分别等待 IEnumerable<Task<T>> C#
Awaiting IEnumerable<Task<T>> individually C#
简而言之,我有一个可枚举的任务,我想以 await 的方式 运行 数组中的每个任务。每个任务都将执行缓慢的网络操作,从我的角度来看,我只需要在任务完成后更新 WinForm UI。
下面是我目前正在使用的代码,但我认为这更像是一种 hack,而不是实际的解决方案:
private void btnCheckCredentials_Click(object sender, EventArgs e)
{
// GetNetCredentials() is irrelevant to the question...
List<NetworkCredential> netCredentials = GetNetCredentials();
// This call is not awaited. Displays warning!
netCredentials.ForEach(nc => AwaitTask(ValidateCredentials(nc)));
}
public async Task<bool> ValidateCredentials(NetworkCredential netCredential)
{
// Network-reliant, slow code here...
}
public async Task AwaitTask(Task<bool> task)
{
await task;
// Dumbed-down version of displaying the task results
txtResults.Text += task.Result.ToString();
}
显示 btnCheckCredentials_Click() 警告的第二行:
Because this call is not awaited, execution of the current method continues before the call is completed. Consider applying the 'await' operator to the result of the call.
这实际上按照我想要的方式工作,因为我不想等待操作完成。相反,我只想取消任务,然后在每个任务完成后立即做一些事情。
Task.WhenAny() 或 Task.WhenAll() 方法的功能与我预期的一样,因为我想知道每项任务是否完成 - 只要它完成。 Task.WaitAll() 或 Task.WaitAny() 是阻塞的,因此也是不可取的。
编辑:所有任务应同时开始。然后他们可以按任何顺序完成。
您可以通过使用 Task.WhenAny
将其标记为 async
来执行此操作(async void
这里很好,因为您在事件处理程序中):
private async void btnCheckCredentials_Click(object sender, EventArgs e)
{
// GetNetCredentials() is irrelevant to the question...
List<NetworkCredential> netCredentials = GetNetCredentials();
var credentialTasks = netCredentials
.Select(cred => ValidateCredentialsAsync(cred))
.ToList();
while (credentialTasks.Count > 0)
{
var finishedTask = await Task.WhenAny(credentialTasks);
// Do stuff with finished task.
credentialTasks.Remove(finishedTask);
}
}
您可以触发并忽略每个任务,并在任务完成时添加回调。
private async void btnCheckCredentials_Click(object sender, EventArgs e)
{
List<NetworkCredential> netCredentials = GetNetCredentials();
foreach (var credential in netCredentials)
{
ValidateCredentails(credential).ContinueWith(x=> ...) {
};
}
}
因此,您可以创建回调方法并确切知道特定任务何时完成,而不是 labda 表达式。
您在寻找 Task.WhenAll
吗?
await Task.WhenAll(netCredentials.Select(nc => AwaitTask(ValidateCredentials(nc)));
您可以在AwaitTask
.
中完成您需要的所有完成处理
await task;
有点尴尬。我会这样做:
public async Task AwaitTask(netCredential credential)
{
var result = await ValidateCredentails(credential);
// Dumbed-down version of displaying the task results
txtResults.Text += result.ToString();
}
简而言之,我有一个可枚举的任务,我想以 await 的方式 运行 数组中的每个任务。每个任务都将执行缓慢的网络操作,从我的角度来看,我只需要在任务完成后更新 WinForm UI。
下面是我目前正在使用的代码,但我认为这更像是一种 hack,而不是实际的解决方案:
private void btnCheckCredentials_Click(object sender, EventArgs e)
{
// GetNetCredentials() is irrelevant to the question...
List<NetworkCredential> netCredentials = GetNetCredentials();
// This call is not awaited. Displays warning!
netCredentials.ForEach(nc => AwaitTask(ValidateCredentials(nc)));
}
public async Task<bool> ValidateCredentials(NetworkCredential netCredential)
{
// Network-reliant, slow code here...
}
public async Task AwaitTask(Task<bool> task)
{
await task;
// Dumbed-down version of displaying the task results
txtResults.Text += task.Result.ToString();
}
显示 btnCheckCredentials_Click() 警告的第二行:
Because this call is not awaited, execution of the current method continues before the call is completed. Consider applying the 'await' operator to the result of the call.
这实际上按照我想要的方式工作,因为我不想等待操作完成。相反,我只想取消任务,然后在每个任务完成后立即做一些事情。
Task.WhenAny() 或 Task.WhenAll() 方法的功能与我预期的一样,因为我想知道每项任务是否完成 - 只要它完成。 Task.WaitAll() 或 Task.WaitAny() 是阻塞的,因此也是不可取的。
编辑:所有任务应同时开始。然后他们可以按任何顺序完成。
您可以通过使用 Task.WhenAny
将其标记为 async
来执行此操作(async void
这里很好,因为您在事件处理程序中):
private async void btnCheckCredentials_Click(object sender, EventArgs e)
{
// GetNetCredentials() is irrelevant to the question...
List<NetworkCredential> netCredentials = GetNetCredentials();
var credentialTasks = netCredentials
.Select(cred => ValidateCredentialsAsync(cred))
.ToList();
while (credentialTasks.Count > 0)
{
var finishedTask = await Task.WhenAny(credentialTasks);
// Do stuff with finished task.
credentialTasks.Remove(finishedTask);
}
}
您可以触发并忽略每个任务,并在任务完成时添加回调。
private async void btnCheckCredentials_Click(object sender, EventArgs e)
{
List<NetworkCredential> netCredentials = GetNetCredentials();
foreach (var credential in netCredentials)
{
ValidateCredentails(credential).ContinueWith(x=> ...) {
};
}
}
因此,您可以创建回调方法并确切知道特定任务何时完成,而不是 labda 表达式。
您在寻找 Task.WhenAll
吗?
await Task.WhenAll(netCredentials.Select(nc => AwaitTask(ValidateCredentials(nc)));
您可以在AwaitTask
.
await task;
有点尴尬。我会这样做:
public async Task AwaitTask(netCredential credential)
{
var result = await ValidateCredentails(credential);
// Dumbed-down version of displaying the task results
txtResults.Text += result.ToString();
}