首页 > 解决方案 > 异步 if 被跳过并且函数跳转到结束

问题描述

我有这个异步功能:

private async Task<bool> ShowAboutToMatchAlert()
{
    bool res = true;

    if(Preferences.Get("WantSeeFirstMatchAlertAgain", true))
    {
        Device.BeginInvokeOnMainThread(async () =>
        {
            bool answer = await DisplayAlert("...");

            if (answer)
            {
                Preferences.Set("WantSeeFirstMatchAlertAgain", false);
                res = true;
            }
            else
            {
                res = false;
            }
        });
    }

    return res; 
}

发生的情况是此功能显示警报。一旦用户选择一个选项(是或否),if(answer)就会触发并根据输入给出结果。

但是,整个函数并没有等待结果,而是立即向前跳到最后的返回。所以总是true被返回(因为函数是异步的)。

该函数本身必须是异步的,才能等待它,因为该函数也是从另一个异步函数调用的。

我怎样才能使这个功能await成为if一部分,而不仅仅是向前跳?

最简单的解决方案当然是让这个函数不是异步的,但是我不能再返回 "true" 或 "false" 但必须返回System.Threading.Task.Task<bool>。所以这不是一个选择。

标签: c#asynchronousxamarin.forms

解决方案


如果Device.BeginInvokeOnMainThread返回无效且无法等待 - 您可以使用它TaskCompletionSource来实现您的目标。此类允许您获取Task(可以等待)并手动设置它的完成结果。然后您的代码变为:

private Task<bool> ShowAboutToMatchAlert()
{
    var tcs = new TaskCompletionSource<bool>();

    if(Preferences.Get("WantSeeFirstMatchAlertAgain", true))
    {
        Device.BeginInvokeOnMainThread(async () => {
            bool answer = await DisplayAlert("...");

            if (answer)
            {
                Preferences.Set("WantSeeFirstMatchAlertAgain", false);
                // signal completion with "true" result
                tcs.SetResult(true);
            }
            else
            {
                // signal completion with "false" result
                tcs.SetResult(false);
            }
        });
    }
    else {
        tcs.SetResult(false);
    }

    return tcs.Task;
}

请注意,应该在所有tcs.SetResult代码路径上调用(or SetCancelledor ) ,包括异常,例如可能由(上面的示例中未显示)产生的异常,否则您可能会陷入令人讨厌的死锁。SetExceptionDisplayAlert


推荐阅读