【问题标题】:Task.Run().Wait() is not working in Onstart() but it is working in App constructor of Xamarin.FormsTask.Run().Wait() 在 Onstart() 中不起作用,但在 Xamarin.Forms 的 App 构造函数中起作用
【发布时间】:2021-01-28 04:33:40
【问题描述】:

我正面临一个有趣的问题,我无法弄清楚可能是什么原因。

我正在尝试处理异步任务以检查我的应用是否有活动订阅。如果在 App Constructor 中完成,它就可以工作。但是放在Onstart()里面就不行了

这里;它正在按我的预期工作。它调用 BillingTasks.WasItemPurchasedAsync() 并等待它完成。

    public App()
    {
        ....
        
        if (!Properties.ContainsKey("IsSubscribed"))
        {
            bool WasPurchased = false;

            Task.Run(async () =>
            {
                WasPurchased = await BillingTasks.WasItemPurchasedAsync();
            }).Wait();
            Application.Current.Properties["IsSubscribed"] = WasPurchased;
        }
        ....
    }

但是当我将相同的代码放在 OnStart() 中时,任务似乎永远不会结束并且它崩溃了。那么造成这种不同行为的原因可能是什么?

    protected override void OnStart()
    {   
        ....
        
        if (!Properties.ContainsKey("IsSubscribed"))
        {
            bool WasPurchased = false;

            Task.Run(async () =>
            {
                WasPurchased = await BillingTasks.WasItemPurchasedAsync();
            }).Wait();
            Application.Current.Properties["IsSubscribed"] = WasPurchased;
        }
        ....
    }

【问题讨论】:

标签: c# asynchronous xamarin.forms xamarin.android


【解决方案1】:

来自Async/Await - Best Practices in Asynchronous Programming 文档,建议优先使用 async Task 方法而不是 async void 方法。

OnStart() 不是事件处理程序,覆盖此方法以在应用程序启动时执行操作。

作为一种变通方法,您可以创建自己的自定义事件和处理程序,以便在您的事件处理程序上执行async void。当应用程序调用OnStart 时,您将订阅该事件,然后引发要异步处理的自定义事件。

 private event EventHandler Starting = delegate { };

    protected override void OnStart()
    {
        //subscribe to event
        Starting += onStarting;
        //raise event
        Starting(this, EventArgs.Empty);
    }

    private async void onStarting(object sender, EventArgs args)
    {
        //unsubscribe from event
        Starting -= onStarting;
        //perform non-blocking actions
        await checksubscriptionAsync();
    }

    private async Task checksubscriptionAsync()
    {
        await ...
    }

【讨论】:

  • 有趣。两个问题。 (1) 你如何保证 onStarting 处理程序执行的工作在需要它的副作用之前完成? (2) 处理程序中的异常是如何观察到的?
  • 感谢您的回复。解决这个问题是件好事。但我需要 checksubscriptionAsync() 在加载 mainPage 之前完成所有检查。使用事件处理程序使应用程序能够继续加载主页..并且大多数情况下,在异步检查完成之前加载的页面。所以似乎最有效的方法是在构造函数中使用 Task.Run().Wait() .
  • @TiTus 所以你最后在构造函数中添加了 Task.Run().Wait()。
  • @Cherry Bu。是的。
【解决方案2】:

任务似乎永远不会结束,它会崩溃。

我不确定为什么会发生这种情况,但可能是 Xamarin 本身在保护您。阻塞 UI 线程对桌面应用程序不利,但在移动设备上尤其被认为是粗鲁的,因为 整个屏幕 变得无响应。出于这个原因,一些应用商店会自动在模拟器中检查这种行为,如果它有这种行为,就会拒绝你的应用。

正确的解决方案是从Async MVVM Data Binding 获取一些用户体验指导。具体来说,您确实希望在完成订阅检查之前阻塞 UI 线程。相反,在异步运行订阅检查时显示某种“正在加载...”屏幕。然后,根据结果,切换到主应用屏幕或注册屏幕或错误屏幕。

【讨论】:

  • 感谢您的回复。我认为,在构造函数中使用 Task.Run().Wait() 也会阻塞 UI,不是吗?实际上,暂时阻塞 UI 对我来说不是问题。我会检查你建议的指导。
猜你喜欢
  • 2021-07-19
  • 1970-01-01
  • 1970-01-01
  • 2021-12-16
  • 2015-07-23
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多