【问题标题】:Xamarin Forms - Progress Bar doesn't update on Android. Works fine on UWPXamarin 表单 - 进度条不会在 Android 上更新。在 UWP 上运行良好
【发布时间】:2021-07-20 12:53:30
【问题描述】:

我正在使用进度条来显示一些 CPU 繁重工作的进度。我创建了一个数组,以便每个元素代表工作迭代之一的完成,并且可以在不影响性能的情况下以线程安全的方式访问,然后我使用 100 毫秒计时器来计算完成了多少次迭代,并在进度条。我在 Task.Run 中完成了所有繁重的工作,因此它应该在另一个线程上运行并且不锁定 UI。当我在 Windows 上测试它时,它完全按预期工作,进度条在屏幕上滚动。当我在 Android 上测试时,无论是在模拟器上还是在我的 8 核物理设备上,它都只是停留在第一位置,直到工作完成。我什至测试了大幅增加工作的迭代次数,以确保它需要更长的时间和相同的结果。它永远不会更新。我不确定我在这里做错了什么。

这就是我正在做的事情:

var CompletedProgress = new int[Iterations];

var ProgressTimer = new Timer(100) { AutoReset = true };
ProgressTimer.Elapsed += async (se, ee) => await Device.InvokeOnMainThreadAsync(() => BreakdownProgress.Progress = CompletedProgress.Sum() / (double)Iterations);
ProgressTimer.Start();

Task.Run(() =>
{ 
    AllResults[0] = GenerateDetails(show, Adjustments, Numbers);
    CompletedProgress[0] = 1;

    Parallel.For(1, Iterations, i =>
    {
        var OrderedNumbers = Numbers.OrderBy(x => Random.NextDouble()).ToArray();
        AllResults[i] = GenerateDetails(show, Adjustments, OrderedNumbers);
        CompletedProgress[i] = 1;
    });
});

我也尝试使用 Binded 属性,并从计时器调用 OnPropertyChanged,结果相同。我还尝试在开始工作之前停止计时器,然后再重新启动它,以防计时器运行得太快。还尝试了 Device.BeginInvokeOnMainThread 而不是 Device.InvokeOnMainThreadAsync。

编辑:我实际上注意到进度条偶尔会上升,但通常不会,而且每当它在开始时移动时,它仍然总是卡住。我仍然可以点击我的工具栏菜单项,所以我认为 UI 线程不会超载。

编辑 2:尝试更新标签而不是进度条,但我遇到了同样的问题,所以问题不在于进度条本身。即使只显示一个简单的计数器,标签上也会出现同样的问题。

编辑 3:将 Parallel.For 更改为常规 for 工作正常!它只是慢得多。所以 Parallel.For 以某种方式阻止了进度条的 UI 更新,以及我拥有的标签示例,但不知何故它并没有阻止工具栏项目正常显示。这太令人困惑了。

【问题讨论】:

    标签: c# android xamarin.forms uwp


    【解决方案1】:

    我想通了。看来我是对的,UI 线程没有被阻塞,但相反,我相信线程池正在过载,并且由于 Parallel.For 使用的所有线程,计时器使用的线程被延迟太久,所以我能够用这个解决它:

    Parallel.For(1, Iterations, new ParallelOptions { MaxDegreeOfParallelism = Environment.ProcessorCount - 1 }, async i =>
    {
                var OrderedNumbers = Numbers.OrderBy(x => Random.NextDouble()).ToArray();
                AllResults[i] = GenerateDetails(show, Adjustments, OrderedNumbers);
                CompletedProgress[i] = 1;
    });
    

    不幸的是,这确实会稍微减慢这个过程,但它确实会恢复动画。如果还有其他方法可以在不阻塞计时器线程的情况下仍然使用完整的 CPU 来执行此操作,请在下面的评论中告诉我。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多