为什么此计数器在 Windows 上正确递增,但在 Android 上却不然?

Why does this counter increment correctly on Windows, but not on Android?

提问人:lomstfer 提问时间:7/22/2023 最后编辑:ToolmakerStevelomstfer 更新时间:7/28/2023 访问量:85

问:

我从 Maui 模板项目开始,您可以在其中单击一个按钮来增加存储在 MainPage 类中的数字。

我删除了除 MainPage.xaml 中的标签之外的所有元素。我将此标签命名为 SpeedLabel,以便可以从 MainPage 类更改它。

<?xml version="1.0" encoding="utf-8" ?>
<ContentPage xmlns="http://schemas.microsoft.com/dotnet/2021/maui"
         xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml"
         x:Class="Metero.MainPage">

<Label
    x:Name="SpeedLabel"
    Text="0"
    SemanticProperties.HeadingLevel="Level1"
    SemanticProperties.Description="Welcome to dot net Multi platform App U I"
    FontSize="80"
    HorizontalOptions="Center" 
    VerticalOptions="Center" />

</ContentPage>

现在,在MainPage C#类(MainPage.xaml.cs)中,我将类更改为:

public partial class MainPage : ContentPage
{
    int count = 0;

    public MainPage()
    {
        InitializeComponent();
        SpeedLabelUpdate();
    }

    private async void SpeedLabelUpdate()
    {
        while (true) {
            count += 1;
            SpeedLabel.Text = count.ToString();
            await Task.Delay(100);
        }
    }
}

我希望这将生成一个应用程序,其数字在屏幕中央不断增加。它在 Windows 上按预期工作,但在 Android 上则不然。

在 Android 上,该数字按预期上升到 9,但随后它被重置为 1,现在更新之间的延迟是 1000 毫秒而不是 100 毫秒。如果我继续运行,它会在达到 9 时再次重置,现在延迟约为 10000 毫秒。

C# Android 异步 MAUI

评论

0赞 Mustafa Özçetin 7/22/2023
我怀疑使用了异步void。请尝试改用异步任务。
0赞 lomstfer 7/22/2023
只需将 void 更改为 Task,问题仍然会出现。
0赞 Mustafa Özçetin 7/22/2023
没那么简单。作为一般规则,不应同步调用方法。async
0赞 lomstfer 7/22/2023
为什么不呢?那么我应该如何处理这个问题呢?
0赞 Mustafa Özçetin 7/22/2023
我看不出有任何理由使用异步。您可以尝试改用计时器。

答:

1赞 Peter Wessberg 7/22/2023 #1

这就是线程安全的方式。尝试看看这是否更适合您。

Dispatcher.StartTimer(TimeSpan.FromMilliseconds(100), () =>
{
    count += 1;
    SpeedLabel.Text = count.ToString();
    return true; 
});

评论

0赞 lomstfer 7/22/2023
谢谢你,但它不起作用!我还有同样的问题!
0赞 Peter Wessberg 7/22/2023
这很奇怪。我已经尝试了您的代码,这两者都对我有用。也许是您的手机或其他原因使 Android 认为代码没有响应或操作系统以某种方式干扰。
0赞 Peter Wessberg 7/23/2023
在更新原始代码中的标签时,您能否看看这是否适合您:Dispatcher.Dispatch(() => SpeedLabel.Text = count。ToString());
0赞 lomstfer 7/23/2023
如果你的意思是这样的:while (true) { count += 1;Dispatcher.Dispatch(() => SpeedLabel.Text = 计数。ToString());等待 Task.Delay(100);} 那么这是同样的问题。
0赞 Peter Wessberg 7/23/2023
很抱歉听到这个消息。我认为这不是编码问题,而是其他问题。
1赞 lomstfer 7/23/2023 #2
private async void SpeedLabelUpdate()
{
    while (true)
    {
        count += 1;
        TempLabel.Dispatcher.Dispatch(() =>
        {
            TempLabel.Text = count.ToString();
        });
        await Task.Delay(100);
    }
}

评论

0赞 lomstfer 7/23/2023
这就是我最终所做的,也是解决问题的原因。
1赞 ToolmakerSteve 7/23/2023
啊,我以为这和你在评论中说的代码相同,不起作用。在这里,您将 Task.Delay 移到了 Dispatch 之外。好;[如果 Task.Delay 在 Dispatch 中,那么循环将尝试运行得非常非常快,因为它没有延迟。Dispatch 内部内容单独运行。该注释中的代码会“堆积”许多 Dispatch,从而导致速度变慢和其他问题。最终会使应用程序崩溃。
0赞 ToolmakerSteve 7/23/2023 #3

这行代码:

SpeedLabelUpdate();

应在 Visual Studio 中显示警告。右?不要忽略该警告。

警告建议添加 .但你不能。这是一个暗示,你正在做的事情是不可靠的await

通过创建一个上下文来修复它,您可以从中:asyncawait

public MainPage()
{
    InitializeComponent();
    // Code inside here runs AFTER "MainPage()" method returns.
    // Use "Dispatcher.Dispatch", because SpeedLabelUpdate touches UI.
    Dispatcher.Dispatch( async() =>
    {
        await SpeedLabelUpdate();
    }
}