BeginInvokeOnMainThread

BeginInvokeOnMainThread

我有一个可以运行的应用程序,但过一会儿,当我在iPhone上调试时,它挂起了手机,并且唯一可以恢复的方法是硬性重置侧面的按钮和主页按钮。

首先,那可能是因为我的应用程序存在内存泄漏吗?

这是该应用程序的代码。特别是,我正在查看BeginInvokeOnMainThread方法。有人可以告诉我是否可以看到实现方式是否有问题?另外,.ContinueWith((arg)的目的是什么。

namespace Japanese
{
    public partial class PhrasesFrame : Frame
    {

        CancellationTokenSource cts = new CancellationTokenSource();

        public PhrasesFrame(PhrasesPage phrasesPage)
        {
            InitializeComponent();
            this.phrasesPage = phrasesPage;
            AS.phrasesFrame = this;
            Device.BeginInvokeOnMainThread(() => ShowCards(cts.Token).ContinueWith((arg) => { }));
        }

        public void Disappearing()
        {
            cts.Cancel();
        }

        public async Task ShowCards(CancellationToken ct)
        {
            AS.cardCountForSelectedCategories = App.DB.GetCardCountForSelectedCategories();
            while (!ct.IsCancellationRequested)
            {

                await Task.Delay(500);
            }
        }
    }
}

最佳答案

继续

首先,让我们解决有关.ContinueWith((arg) => { }))的问题。原始ContinueWith完成后,Task告诉更多代码要执行。在我们的例子中,ContinueWith完成后,Device.BeginInvokeOnMainThread(() => ShowCards(cts.Token)内部的代码将运行。

在这种情况下,ContinueWith内没有任何代码,因此我们可以将其删除。

冷冻

是的,我可以看到这段代码有可能卡住UI。
BeginInvokeOnMainThread将使Action排队以在主线程(也称为UI线程)上运行。主线程一直在监听用户的输入(点击屏幕上的按钮,捏缩放等),如果该线程正忙于执行长时间运行的任务,它将无法响应用户的输入。输入直到完成;因此您的应用将显示为卡住状态。

主线程正在调用代码await Task.Delay(500);。因此,我们告诉主线程将自身卡住500毫秒,并无限循环。

一种解决方案是将该代码包装在Task.Run中,将其放在后台线程中,并释放主线程以监听/响应用户输入。

Task.Run(async () =>
{
    while (!ct.IsCancellationRequested)
    {
          await Task.Delay(500);
    }
}

更多线程建议
  • 仅在需要更新UI时使用BeginInvokeOnMainThread。 99%的代码可以在后台线程上运行而没有问题。 1%是用于更新UI的代码。任何更新UI的代码都必须在主线程上运行。
  • 如果执行任务所花费的时间比屏幕刷新率长,请在后台线程上执行该任务。例如,如果屏幕的刷新率是60Hz,则它每16.7ms每秒更新60次。因此,如果我们有一段代码需要20毫秒的时间来执行,则需要在后台线程上执行它,以确保我们不会卡住应用程序并丢弃任何帧。
  • 上面的代码似乎正在访问数据库,我强烈建议您将其移至像
  • 这样的后台线程

    await Task.Run(() => AS.cardCountForSelectedCategories = App.DB.GetCardCountForSelectedCategories());

    10-01 22:00