c# - .net c# 等待异步事件完成并且代码中仍有 "synchronous"流的最佳方法

标签 c# .net asynchronous

我的一般性问题是:如何编写仍然清晰易懂的异步代码,就像同步解决方案一样?

我的经验是,如果您需要使用 BackgroundWorker 之类的东西使一些同步代码异步,您将不再有一系列易于遵循的程序语句来表达您的总体意图和事件顺序,您最终会得到一个一堆“完成”的事件处理程序,每个都启动下一个 BackgroundWorker,生成的代码真的很难理解。

我知道这不是很清楚;更具体的东西:

假设我的 WinForms 应用程序中的一个函数需要启动一些亚马逊 EC2 实例,等待它们开始运行,然后等待它们全部接受 SSH 连接。伪代码中的同步解决方案可能如下所示:

instances StartNewInstances() {
    instances = StartInstances()
    WaitForInstancesToBecomeRunning(instances)
    WaitForInstancesToAcceptSSHConnection(instances).
    return (instances)
    }

这很好。发生的事情很清楚,程序 Action 的顺序也很清楚。没有白噪声会分散您对代码和流程的理解。我真的很想得到看起来像那样的代码。

但实际上,我没有同步解决方案.. 这些功能中的每一个都可以运行很长时间,并且每个功能都需要执行以下操作:更新用户界面,监控是否超时,然后重试定期操作,直到成功或超时。简而言之,这些都需要在后台发生,以便前台 UI 线程可以继续。

但如果我使用像 BackgroundWorker 这样的解决方案,我似乎不会像上面那样得到很好的易于遵循的程序逻辑。相反,我可能会从我的 UI 线程启动一个后台工作程序来执行第一个功能,然后我的 ui 线程在工作线程运行时返回到 UI。当它完成时,它的“完成”事件处理程序可能会启动下一个后台 worker 。当它完成时,它的“完成”事件处理程序可能会启动最后一个 BackgroundWorker,等等。这意味着您必须“跟踪”完成事件处理程序才能了解整个程序流程。

必须有更好的方法 a) 让我的 UI 线程响应,b) 让我的异步操作能够更新 ui,最重要的是 c) 能够将我的程序表达为一系列连续的步骤(如我已经在上面展示了)以便有人可以理解结果代码

任何和所有输入将不胜感激! 迈克尔

最佳答案

My generalized question is this: how do you write asynchronous code that is still clear and easy to follow, like a synchronous solution would be?

您等待 C# 5。现在不会太久了。 async/await岩石。您确实在上面的句子中描述了该功能...请参阅 Visual Studio async homepage用于教程、语言规范、下载等。

目前,确实没有非常干净的方式 - 这就是为什么首先需要该功能的原因。异步代码很自然地变得一团糟,尤其是当您考虑错误处理等时。

您的代码将表示为:

async Task<List<Instance>> StartNewInstances() {
    List<Instance> instances = await StartInstancesAsync();
    await instances.ForEachAsync(x => await instance.WaitUntilRunningAsync());
    await instances.ForEachAsync(x => await instance.WaitToAcceptSSHConnectionAsync());
    return instances;
}

这是假设有一些一点的额外工作,例如 IEnumerable<T> 上的扩展方法用表格

public static Task ForEachAsync<T>(this IEnumerable<T> source,
                                   Func<T, Task> taskStarter)
{
    // Stuff. It's not terribly tricky :(
}

关于c# - .net c# 等待异步事件完成并且代码中仍有 "synchronous"流的最佳方法,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/11674490/

相关文章:

c# - 在 C# 中实现复杂数字格式的最佳方法

c# - 我如何在运行时在 asp.net 中添加新面板

c# - .net 远程处理 : Update already serialized objects

c# - 文本文件中的换行符 (C#)

javascript - 异步函数不是按顺序调用的

javascript - 自动滚动div问题

c# - 如何使用项目和一个文本框填充组合框

c# - 调用 `Environment.GetEnvironmentVariable`影响后续调用

c# - 检测一个方法在没有锁的情况下被调用

java - 对象化 GAE/J Google App Engine : Understanding asynchronous load