gpt4 book ai didi

c# - 等待事件从任务列表中触发

转载 作者:太空宇宙 更新时间:2023-11-03 17:51:47 25 4
gpt4 key购买 nike

我正在使用Task.Run()启动多个任务。在上述每个任务中,我为InstallCompleted定义了一个事件处理程序。然后,我await完成这些任务。棘手的是,下面看到的installModule.Install()方法会立即返回,因为它在内部调用了OneWay WCF服务调用。

因此,在上述每个任务中所有await实例都触发了各自的installModule事件之前,我该如何InstallCompleted?如果有更好的方法可以做到这一点,我全神贯注。

var installTasks = new List<Task>();

foreach (var targetMachine in vm.TargetMachines)
{
var installTask = Task.Run(() =>
{
foreach (var module in Modules)
{
var installModule = module as IInstallModule; // copy closure variable
if (installModule == null)
continue;

installModule.InstallCompleted += (s, e) =>
{
//TODO set some flag indicating this install is complete
};

var ip = new Progress<InstallProgress>();
installModule.Install(targetMachine.MachineName, ip);
}
});

installTasks.Add(installTask);
}

await Task.WhenAll(installTasks); // unblocks immediately because installModule.Install() above returns immediately

最佳答案

每当您interoperating async with another kind of asynchronous API时,都可以将TaskCompletionSource<T>用作异步一次性信号。就个人而言,我喜欢将此作为扩展方法:

public static Task<InstallCompletedResult> InstallAsync(
this IInstallModule module, string machineName,
IProgress<InstallProgress> progress = null)
{
var tcs = new TaskCompletionSource<InstallCompletedResult>();
InstallCompletedEventHandler handler = null;
handler = (s, e) =>
{
module.InstallCompleted -= handler;
if (e.Exception != null)
tcs.TrySetException(e.Exception);
else
tcs.TrySetResult(e.Result);
};
module.InstallCompleted += handler;
module.Install(machineName, progress);
return tcs.Task;
}


一旦有了互操作性,就可以很容易地进行消费:

var installTask = Task.Run(async () =>
{
var tasks = new List<Task>();
foreach (var module in Modules)
{
var installModule = module as IInstallModule; // copy closure variable
if (installModule == null)
continue;

var ip = new Progress<InstallProgress>();
tasks.Add(installModule.InstallAsync(targetMachine.MachineName, ip));
}
});


或者,更简单地说:

var installTask = Task.Run(async () =>
{
var tasks = Modules.OfType<IInstallModule>()
.Select(module => module.InstallAsync(targetMachine.MachineName,
new Progress<InstallProgress>()));
await Task.WhenAll(tasks);
});

关于c# - 等待事件从任务列表中触发,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/23397906/

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