c# - 使用 Xamarin MessagingCenter 调用异步方法时如何处理异步和等待?
问题描述
在我的虚拟机中,我有这个:
public ICommand FBtnCmd;
public PhrasesFrameViewModel(PhrasesFrame phrasesFrame) {
FBtnCmd = new Command(() => MessagingCenter.Send<PhrasesFrameViewModel>(this, "FBtn"));
}
在后端 C# 我有这个:
public PhrasesFrame()
{
InitializeComponent();
MessagingCenter.Subscribe<PhrasesFrameViewModel>(this, "FBtn", (s) => this.FBtn());
}
async public Task FBtn()
{
// code here
await Task.Run(() => App.DB.UpdateFavorite(phrase.Favorite, phrase.PhraseId));
// code here
}
它给了我一条警告信息,说
由于不等待此调用,因此在调用完成之前继续执行当前方法。考虑将“等待”运算符应用于调用结果。
解决方案
我认为警告已经上Subscribe
线。这种情况类似于也不是异步的控制事件处理程序所发生的情况。lambda(s) => this.FBtn()
基本上是一个委托Action<PhrasesFrameViewModel>
,其签名的返回类型为void
. 因此,如果您在内部开始异步工作 - 就像这里一样FBtn
,您将“触发并忘记”,因此该操作将在第一个实际异步工作开始执行后立即完成。这种方法可以称为“即发即弃”,不建议这样做,因为如果在执行过程中发生任何异常FBtn
,异常将永远不会向上传播,并且您的应用程序可能会在您不知道的情况下进入不一致的状态。如果有FBtn
可能抛出,你应该使用一个try...catch
块来代替:
async (s) => try { await this.FBtn(); } catch { /* handle */ }
我必须在这里制作 lambda async void
,才能await
将FBtn
Task
. 没有await
,FBtn
将触发并忘记,并且此处不会发生潜在的异常,因为它会在 内部Task
,永远awaited
也不会通过GetResult()
或类似方法访问。
简而言之,您应该始终await
避免Task
火灾和忘记。唯一可以的地方async void
是事件处理程序和类似的情况,但您应该始终考虑潜在的异常。
推荐阅读
- git - fork 一个 expo 模块以及如何维护它
- android - 如何向flutter请求CHANGE_WIFI_MULTICAST_STATE权限
- mysql - MIN 带 CASE 表达式
- vue.js - v-model.trim 和 v-model 有什么区别?
- elasticsearch - 如何在 Elasticsearch 中修改多个索引名称
- node.js - 填充动态字段 Mongoose
- prometheus - Prometheus 仅在最后 5 分钟时间范围内不返回数据
- java - 将活动另存为 PDF,但会生成空的 pdf 文件
- sql - 计算运行库存值。如果为零,则乘以先前的值
- javascript - 组件异常错误:文本字符串必须在
零件