Xamarin.Android RunOnUIThread 和 onTimedEvent 延迟/滞后(我正在尝试显示倒数计时器)

Posted

技术标签:

【中文标题】Xamarin.Android RunOnUIThread 和 onTimedEvent 延迟/滞后(我正在尝试显示倒数计时器)【英文标题】:Xamarin.Android RunOnUIThread and onTimedEvent delay/lags (I am trying to display a CountDown Timer) 【发布时间】:2017-10-22 04:50:17 【问题描述】:

所以我正在创建一个显示从 3 到 0 的倒计时的应用程序,用户可以单击重试,这将再次从 3 到 0 开始。我有显示倒数计时器的 tvTimer(TextView)。

代码工作正常,但有时会滞后/延迟,例如

当 onCreate 时,tvTimer.Text 将显示 3、2、1、0,但是当我单击重试按钮时,有时它会显示 3、2、2、0。

你认为是因为 RunOnUIThread 吗?

这是我的代码

    int CountSeconds;
    Button retry;
    TextView tvTimer;
    System.Timers.Timer aTimer = new System.Timers.Timer();

    protected override void OnCreate(Bundle savedInstanceState)
    
        base.OnCreate(savedInstanceState);
        SetContentView(Resource.Layout.Pagee);
        tvTimer = FindViewById<TextView>(Resource.Id.tvTimer);
        retry = FindViewById<Button>(Resource.Id.retry);
        aTimer.Interval = 1000;
        aTimer.Elapsed += OnTimedEvent;

        play_timer();
        retry.Click += Retry_Click;
    

    public void play_timer()
    
         CountSeconds = 3; 
         aTimer.Start();
    

    private void OnTimedEvent(object source, ElapsedEventArgs e)
    
        RunOnUiThread(() =>  tvTimer.Text = Convert.ToString(CountSeconds ););

        CountSeconds  = CountSeconds  - 1;

        if (CountSeconds  == 0)
        
            CountSeconds  = 3;
            aTimer.Stop();
        

    private void Retry_Click(object sender, EventArgs e)
    
             play_timer();
    

谢谢!!!

【问题讨论】:

您在 UI 线程上运行代码并在另一个线程中更改值。这将是一个竞争条件,并且任何一个都可能发生在另一个之前。最好先减法,然后设置值,或者在同一个 UI 线程中进行整个减法。 @SamiKuhmonen 您好,感谢您的回复!很抱歉,但我完全是新手,不了解先减法然后设置值,我应该先在哪里减法?谢谢! 【参考方案1】:

如果您编写在不同线程上运行的代码,例如这里

RunOnUiThread(() =>  tvTimer.Text = Convert.ToString(CountSeconds ););

CountSeconds  = CountSeconds  - 1;

这意味着这些部分中的任何一个都可以先运行,或者它们甚至可以在多核/CPU 系统上同时运行。例如,如果CountSeconds 为 3,您可能会在文本框中得到 3 或 2。

为了确保事情以更可重现的顺序发生,您可以重新排序这些事情并将RunOnUiThread 移动到方法的末尾。然后你可以确定减法和零检查首先发生并且只有在设置文本框之后发生。

您还可以将调用中的整个逻辑移动到 UI 线程,以便它在同一个线程中立即发生,例如:

RunOnUiThread(() => 
  CountSeconds  = CountSeconds  - 1;

  tvTimer.Text = Convert.ToString(CountSeconds );

  if (CountSeconds  == 0)
  
    CountSeconds  = 3;
    aTimer.Stop();
  
);

【讨论】:

非常感谢,这对您有很大帮助。我有最后一个问题。如果我在 onTimedEvent 运行时单击“重试”按钮会怎样?它也可以在不同的线程上运行,对吗?所以假设它从 3、2 开始运行,然后我单击 Retry,它将再次将 CountSeconds 的值设置为 3。会发生什么?我试过了,好像乱七八糟(号码更新延迟) @CarmenC 该事件运行时间很短,所以这无关紧要。但是,如果您希望它保持同步,您应该停止计时器,重置值,然后再次启动计时器。理论上有可能这恰好发生在计时器事件运行时,所以如果它很重要,您可以随时向系统添加锁定,以确保您在 UI 更新时不做任何事情。

以上是关于Xamarin.Android RunOnUIThread 和 onTimedEvent 延迟/滞后(我正在尝试显示倒数计时器)的主要内容,如果未能解决你的问题,请参考以下文章

Xamarin.Forms 是 Xamarin.Android、Xamarin.IoS 和 Xamarin.Win 的简单总和吗?

xamarin android开发 两个按钮 怎么放在同一排上

抽屉布局在 Xamarin.Android.Support.Core.UI 和 Xamarin.Android.Support.V4 中都存在

无法使用 Xamarin.Android 中的 Xamarin.Mobile 组件保存联系人

将Xamarin.Android应用程序迁移到Xamarin.Forms应用程序

dotnet 5 和 Xamarin Android:找不到导入的项目“Xamarin.Android.CSharp.targets”