简体   繁体   English

Xamarin Forms - Android 上的进度条未更新。 在 UWP 上工作正常

[英]Xamarin Forms - Progress Bar doesn't update on Android. Works fine on UWP

I'm using a progress bar to show the progress of some CPU heavy work.我正在使用进度条来显示一些 CPU 繁重工作的进度。 I create an array so that each element represents completion of one of the iterations of the work, and can be accessed thread safe without impacting performance, and then I use a 100ms Timer to calculate how many iterations have completed, and display that progress on the ProgressBar.我创建了一个数组,以便每个元素代表工作迭代之一的完成,并且可以在不影响性能的情况下以线程安全的方式访问,然后我使用 100 毫秒计时器来计算完成了多少次迭代,并在进度条。 I do all the heavy work in a Task.Run so it should be running on another thread and not locking the UI.我在 Task.Run 中完成了所有繁重的工作,因此它应该在另一个线程上运行而不是锁定 UI。 When I test it on Windows, it works exactly as expected, the progress bar scrolls across the screen.当我在 Windows 上测试它时,它完全按预期工作,进度条在屏幕上滚动。 When I test on Android, both on the Emulator as well as my 8 core physical device, it just stays in the first position until the work is done.当我在模拟器和我的 8 核物理设备上测试 Android 时,它只停留在第一个 position 中,直到工作完成。 I even tested increasing the iterations of the work considerably to make sure it takes longer, and same result.我什至测试了大幅增加工作的迭代,以确保它需要更长的时间,并且结果相同。 It never updates.它永远不会更新。 I'm not really sure what I'm doing wrong here.我不确定我在这里做错了什么。

Here's what I'm doing:这就是我正在做的事情:

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;
    });
});

I also tried using a Binded property, and calling OnPropertyChanged from the timer, and it was the same result.我还尝试使用 Binded 属性,并从计时器调用 OnPropertyChanged,结果相同。 I also tried stopping the timer before doing its work and then restarting it as well, in case the timer was running too quickly.我还尝试在开始工作之前停止计时器,然后再重新启动它,以防计时器运行得太快。 Also tried Device.BeginInvokeOnMainThread instead of Device.InvokeOnMainThreadAsync.还尝试了 Device.BeginInvokeOnMainThread 而不是 Device.InvokeOnMainThreadAsync。

Edit: I have actually noticed the progress bar go up occasionally, but not usually, and whenever it does move at the start, it still always gets stuck.编辑:我实际上已经注意到进度条 go 偶尔会上升,但通常不会,而且每当它在开始时移动时,它仍然总是卡住。 I can still tap my toolbar menu items so I don't think the UI thread is overloaded.我仍然可以点击我的工具栏菜单项,所以我认为 UI 线程不会超载。

Edit 2: Tried updating a label instead of a progress bar and I get the same issue, so the issue isn't with the progressbar itself.编辑 2:尝试更新 label 而不是进度条,我遇到了同样的问题,所以问题不在于进度条本身。 Even displaying just a simple counter has the same problem on the label.即使只显示一个简单的计数器,在 label 上也会出现同样的问题。

Edit 3: Changing Parallel.For to regular for works fine.编辑 3:将 Parallel.For 更改为常规 for 工作正常。 It's just much slower.它只是慢得多。 So Parallel,For is somehow blocking the UI updating for the progress bar, and the label example I had.所以 Parallel,For 以某种方式阻止了进度条的 UI 更新,以及我的 label 示例。 but somehow it's not blocking the toolbar items from displaying just fine.但不知何故,它并没有阻止工具栏项目正常显示。 This is so confusing.这太令人困惑了。

I figured it out.我想到了。 It appears I was right that the UI thread wasn't being blocked, but instead I believe the thread pool was being overloaded and the threads used by the timer were being delayed too long because of all of the threads used by Parallel.For, so I was able to solve it with this:看起来我是对的,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;
});

Unfortunately this does slow the process slightly, but it does bring the animation back.不幸的是,这确实稍微减慢了这个过程,但它确实让 animation 回来了。 If there's another way to still use the full CPU to do this, without blocking the timer thread, let me know in a comment below.如果还有另一种方法可以在不阻塞计时器线程的情况下仍然使用完整的 CPU 来执行此操作,请在下面的评论中告诉我。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM