Mar*_*man 1 c# wcf asynchronous async-await
我开始使用几个任务Task.Run().在每个任务中,我为其定义了一个事件处理程序InstallCompleted.然后,我await完成这些任务.棘手的是,installModule.Install()下面看到的方法立即返回,因为它在内部调用OneWayWCF服务调用.
那么,在上述每项任务中的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
Run Code Online (Sandbox Code Playgroud)
每当您与其他类型的异步API进行互操作async时,您都可以将其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;
}
Run Code Online (Sandbox Code Playgroud)
一旦你有了互操作件,消费它是非常简单的:
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));
}
});
Run Code Online (Sandbox Code Playgroud)
或者,更简单:
var installTask = Task.Run(async () =>
{
var tasks = Modules.OfType<IInstallModule>()
.Select(module => module.InstallAsync(targetMachine.MachineName,
new Progress<InstallProgress>()));
await Task.WhenAll(tasks);
});
Run Code Online (Sandbox Code Playgroud)
| 归档时间: |
|
| 查看次数: |
126 次 |
| 最近记录: |