通过开发一个可以通过串行通信来控制复杂硬件的大型WPF应用程序,我是一个很好的方法。在应用程序“堆栈”的最底部,我有一个串行通信层(利用.Net'SerialPort'类)。读取和写入h / w设备是系统的基本部分,由业务逻辑层的许多不同区域使用,通常散布着复杂的科学计算和其他这样的逻辑;这些BLL方法又从整个UI层调用。
目前,业务逻辑层中的所有内容(包括SerialPort读写)都是同步。我使用async / await的唯一一次是在UI层,通常是在调用业务逻辑时。在这里,我将把呼叫包裹在Task.Run()
中,例如: -
private async void SomeButtonClick(object sender, EventArgs e)
{
await Task.Run(() => _someBLLService.TurnPumpOn());
}
这是一个需要几毫秒的简单示例。一个更复杂的例子是开始一个长期运行的过程(再次使用上述技术);此业务逻辑“服务”将运行几秒或几分钟,从硬件收集数据并在此期间执行其他“控制”功能。它会定期将数据广播回UI,以便在图表上绘图(通过pubsub事件聚合器框架)。上述技术运行良好,允许UI在进行此类业务层过程时保持响应。
我最近一直在考虑“一直异步”,从串行通信代码开始(例如使用.ReadAsync
),但这会对整个系统产生影响。数十个(如果不是数百个)业务逻辑方法需要重构为异步方法,直到UI层。在这里,我可以稍微简化上面的代码:
private async void SomeButtonClick(object sender, EventArgs e)
{
await _someBLLService.TurnPumpOn();
}
虽然我不反对解决大型重构工作,但我想知道它的好处是什么。许多人(如Stephen Cleary)提倡“异步一路”解决方案,但主要目标似乎是在调用长时间运行的BLL流程时保持UI响应,我的Task.Run()
技术已经做到了
答案 0 :(得分:7)
由于您的应用程序(可能)不是高负载且是GUI应用程序,因此使用异步和等待的唯一原因是提高生产力。吞吐量和可扩展性无法进入画面。
因此,做最方便的事情。这很可能是您在示例代码中使用的await Task.Run
模式。
但这会对整个系统产生影响
是。 Async具有明显的生产力成本,并且具有传染性。只有这样才能明确表达您从该选择中获得的好处。在这里,唯一的好处是您的UI代码更短一些字符。这是两个代码片段之间的区别。整个系统的其余部分都变得更糟。
也许你一直在关注C#社区并且一路走向异步的趋势。程序员很容易在不理解它们的情况下跳转到魔术解决方案。许多异步的拥护者甚至无法阐明他们从中获得的具体好处。还有很多小组也在想。不要仅依靠互联网建议做出决定。要考虑到自己有什么意义。