Tizen Watch App中的不确定错误

问题描述

我正在尝试为Samsung galaxy Watch创建一个简单的计数器应用程序,该应用程序可响应边框并具有加/减按钮以分别增加/减少计数器。当计数器值低于某些阈值时,其颜色应更改(例如,当它接近0时,从白色变为橙色再变为红色)。这些按钮应该能够保持按下状态,以使计数器在稍稍延迟直到松开之前迅速增加/减少。此功能通常有效,除了按下按钮时有时会出现不确定性错误。通过检查我的代码,应该没有任何问题,但是也许我遗漏了一些东西。这是一个复制问题的SCCM:

using System;
using System.Collections.Generic;
using System.Timers;
using Tizen.Wearable.CircularUI.Forms;
using Xamarin.Forms;

namespace RepeatableCounter
{
    class Program : global::Xamarin.Forms.Platform.Tizen.FormsApplication
    {
        protected override void OnCreate()
        {
            base.OnCreate();
            LoadApplication(new App());
        }

        static void Main(string[] args)
        {
            var app = new Program();
            Forms.Init(app);
            global::Tizen.Wearable.CircularUI.Forms.FormsCircularUI.Init();
            app.Run(args);
        }
    }

    class App : Application
    {
        public App()
        {
            MainPage = new MainPage { Value = 20,Thresholds = { (5,Color.Red),(10,Color.Orange) }};
        }
    }

    class MainPage : BezelInteractionPage,IRotaryEventReceiver
    {
        private int value;
        private int ticks;
        private readonly Label counter;
        private readonly Timer resetTicks;

        public MainPage() : base()
        {
            value = 0;
            ticks = 0;

            counter = new Label
            {
                Text = value.ToString(),FontSize = 32,BackgroundColor = Color.Transparent,HorizontalTextAlignment = TextAlignment.Center
            };
            RepeatButton plusButton = new RepeatButton
            {
                Text = "+",Delay = 500,Interval = 100,HorizontalOptions = Layoutoptions.Center,WidthRequest = 60
            };
            RepeatButton minusButton = new RepeatButton
            {
                Text = "\u2212",WidthRequest = 60
            };

            Content = new StackLayout
            {
                VerticalOptions = Layoutoptions.Center,Spacing = -24,Children = {
                    plusButton,counter,minusButton
                }
            };

            RotaryFocusObject = this;
            resetTicks = new Timer
            {
                Interval = 500,Enabled = false,AutoReset = false,};
            resetTicks.Elapsed += (sender,e) => ticks = 0;

            plusButton.pressed += (sender,e) => Value++;
            plusButton.Held += (sender,e) => Value++;
            minusButton.pressed += (sender,e) => Value--;
            minusButton.Held += (sender,e) => Value--;
        }
        public int Value
        {
            get { return value; }
            set
            {
                this.value = value;
                counter.Text = this.value.ToString();

                Color selected = Color.Default;
                foreach ((int threshold,Color color) in Thresholds)
                {
                    if (value <= threshold)
                    {
                        selected = color;
                        break;
                    }
                }
                counter.TextColor = selected;
            }
        }

        public int TickThreshold { get; set; } = 10;

        public int FastTickStep { get; set; } = 5;

        public IList<(int,Color)> Thresholds { get; set; } = new List<(int,Color)>();

        public void Rotate(RotaryEventArgs args)
        {
            if (args.IsClockwise)
            {
                if (ticks >= 0)
                    ticks++;
                else
                    ticks = 1;
                if (ticks <= TickThreshold)
                    Value++;
                else
                    Value += FastTickStep;
            }
            else
            {
                if (ticks <= 0)
                    ticks--;
                else
                    ticks = -1;
                if (ticks >= -TickThreshold)
                    Value--;
                else
                    Value -= FastTickStep;
            }

            resetTicks.Stop();
            resetTicks.Start();
        }
    }

    public class RepeatButton : Button
    {
        private readonly Timer timer;

        public RepeatButton() : base()
        {
            timer = new Timer
            {
                Enabled = false,AutoReset = true
            };
            timer.Elapsed += (sender,e) => {
                timer.Interval = Interval;
                Held.Invoke(timer,e);
            };

            pressed += (sender,e) => {
                timer.Interval = Delay;
                timer.Start();
            };
            Released += (sender,e) => timer.Stop();
        }

        public double Delay { get; set; } = 100;

        public double Interval { get; set; } = 100;

        public event EventHandler Held;
    }
}

要复制问题,请按住+和/或-按钮。由于问题不是确定性的,因此您可能偶尔需要切换按钮。我大多数时候都看到它是在颜色改变后发生的。

我遇到了三个“症状”:

  • 标签消失
  • 按钮不响应其Release事件(即使释放按钮,计数器仍在计数)
  • 发生分段错误(我已经看到它在上面代码的第22行和第91行中报告)

添加更多UI元素似乎加剧了该问题并导致错误发生得更快,并且这在模拟器和实际手表中均会发生。我缺少某种同步或线程问题吗?是什么原因导致这些错误

解决方法

请使用Device.StartTimer代替System.Threading.TimerSystem.Threading.Timer使用辅助线程,因此它不应直接访问UI

要在UI线程上执行代码,可以使用Device.BeginInvokeOnMainThread

相关问答

Selenium Web驱动程序和Java。元素在(x,y)点处不可单击。其...
Python-如何使用点“。” 访问字典成员?
Java 字符串是不可变的。到底是什么意思?
Java中的“ final”关键字如何工作?(我仍然可以修改对象。...
“loop:”在Java代码中。这是什么,为什么要编译?
java.lang.ClassNotFoundException:sun.jdbc.odbc.JdbcOdbc...