首页 > 解决方案 > 使用 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
}

它给了我一条警告信息,说

由于不等待此调用,因此在调用完成之前继续执行当前方法。考虑将“等待”运算符应用于调用结果。

标签: c#xamarinxamarin.forms

解决方案


我认为警告已经上Subscribe线。这种情况类似于也不是异步的控制事件处理程序所发生的情况。lambda(s) => this.FBtn()基本上是一个委托Action<PhrasesFrameViewModel>,其签名的返回类型为void. 因此,如果您在内部开始异步工作 - 就像这里一样FBtn,您将“触发并忘记”,因此该操作将在第一个实际异步工作开始执行后立即完成。这种方法可以称为“即发即弃”,不建议这样做,因为如果在执行过程中发生任何异常FBtn,异常将永远不会向上传播,并且您的应用程序可能会在您不知道的情况下进入不一致的状态。如果有FBtn可能抛出,你应该使用一个try...catch块来代替:

async (s) => try { await this.FBtn(); } catch { /* handle */ }

我必须在这里制作 lambda async void,才能awaitFBtn Task. 没有awaitFBtn将触发并忘记,并且此处不会发生潜在的异常,因为它会在 内部Task,永远awaited也不会通过GetResult()或类似方法访问。

简而言之,您应该始终await避免Task火灾和忘记。唯一可以的地方async void是事件处理程序和类似的情况,但您应该始终考虑潜在的异常。


推荐阅读