前往小程序,Get更优阅读体验!
立即前往
发布
社区首页 >专栏 >使用 await 实现业务对 UI 的控制反转

使用 await 实现业务对 UI 的控制反转

作者头像
jgrass
发布2024-12-25 16:37:20
发布2024-12-25 16:37:20
5500
代码可运行
举报
文章被收录于专栏:蔻丁杂记蔻丁杂记
运行总次数:0
代码可运行

背景:WPF/WinForm 桌面程序开发

问题

在涉及到与用户交互的业务场景下,经常容易在界面的后台代码(也就是 xxx.xaml.cs)中编写业务逻辑,在这里调用业务层提供的方法。

如此一来,UI 的后台代码会变得臃肿,职责不清晰。而且由于与界面的耦合太深,后期修改需求会非常麻烦。

问题出在哪?

UI 应该只是提供基本的用户交互,不应该成为业务逻辑的控制中心,需要将业务代码放到独立的模块中,业务代码通过接口来调用 UI,以实现用户的交互。

控制反转 是指:应该有业务层代码调用 UI,而不是 UI 调用业务逻辑代码。

当然,最开始的调用一般是由 UI 发起的,这里强调的是:流程与逻辑的控制代码,应该在远离 UI 的业务层,UI 只负责用户交互。

改善措施

容易想到的改善办法是:在 UI 中定义事件,业务层订阅事件,以获取用户操作的结果。

这样做是可以的,但实际写起代码来就会发现,使用事件订阅的方式,容易造成执行逻辑的割裂,代码的可读性会变得很差。

既然要等待用户操作的结果,除了事件之外,能否实现同步的等待呢?

比如,一个笨办法就是:写一个 while(true) 循环,不断检测用户是否完成了操作,如果完成了,就返回操作结果。

这样就不用使用事件调来调去了,可以同步等待用户完成操作。

使用 await

当然,while(true) 的方案不会是真实的措施,使用 await 就可以实现这样的效果。 本质是,一个可等待的对象 awaiter 内部有一个通知机制,当你 await 一个对象之后,就会一直阻塞,等待通知。像不像是对事件的一种封装?哈哈。

这个通知机制就是 INotifyCompletion Interface (System.Runtime.CompilerServices) | Microsoft Docs

代码就是:await 用户操作(); ,如果用户操作没有完成,则这里就阻塞。 如此一来,业务逻辑写起来就会顺畅很多。

具体实现原理与方法可以看:

在 WPF/UWP 中实现一个可以用 await 异步等待 UI 交互操作的 Awaiter - walterlv

Demo 分析

Demo:Jasongrass/DemoPark - 码云 - 开源中国

使用事件实现的流程控制代码:

代码语言:javascript
代码运行次数:0
复制
public void DoFlow(){    _isUnderFlowing = true;    Step1();}
private void OnUserInputFinished(object sender, string inputContent){    // 状态判断,如有没有执行 Step1 等。如果状态判断OK,则执行 Step2。    if (!_isUnderFlowing)    {        return;    }    var precessResult = Step2(inputContent);    StepEnd();
    // 外部如何拿到 precessResult?}

会发现,整个流程被分成了两部分,而且没法很好地返回最终处理结果(因为代码在事件的响应里面)。

使用 awaiter 实现的流程控制代码:

代码语言:javascript
代码运行次数:0
复制
public async Task<string> DoFlowAsync(){    Step1();    var inputContent = await UserInputViewHandler.GetUserInputAsync();    var precessResult = Step2(inputContent);    StepEnd();    return precessResult;}

可以在一个函数里面,处理所有的逻辑。

更重要的是,这里还是只有一个 UI 交互的场景,在需要更多的 UI 交互时,如果使用事件的实现方式,代码理解起来将是一个灾难。

核心代码

UI 部分要支持这种调用当时,需要的核心代码其实很少。

使用 walterlv 封装的这个 DispatcherAsyncOperation 类,实现对用户操作的 awaiter 等待,会很轻松。

基础原理文章:

在 WPF/UWP 中实现一个可以用 await 异步等待 UI 交互操作的 Awaiter - walterlv

Demo源代码:

Jasongrass/DemoPark - 码云 - 开源中国


原文链接: https://cloud.tencent.com/developer/article/2481502

本作品采用 「署名 4.0 国际」 许可协议进行许可,欢迎转载,但未经作者同意必须保留此段声明,且在文章页面明显位置给出原文链接。

本文参与 腾讯云自媒体同步曝光计划,分享自作者个人站点/博客。
原始发表:2020年2月14日 ,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 作者个人站点/博客 前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体同步曝光计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
目录
  • 问题
  • 改善措施
  • 使用 await
  • Demo 分析
  • 核心代码
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档