Xamarin:仅在时间阈值,并发问题之后显示微调器

时间:2017-09-27 18:51:17

标签: c# multithreading xamarin xamarin.ios

我在Xamarin.iOS中使用BTProgressHUD在UI上显示一个微调器。当满足以下两个条件时,我想展示微调器:

  1. 已经过了一定的时间(一些门槛,比如50ms)
  2. 旋转器尚未被标记为已被解雇。
  3. 我在自定义对象中持有操作/微调器的状态:

    internal class SpinnerInfo, IDisposable
    {
        public string Context; // The calling method, for telemetry
        public string UserMessage; // The message to show on the spinner
        public Stopwatch Timer; // To time how long the spinner is on the screen for telemetry
        protected object _stopLock = new object();
        private Timer _delayTimer;
    
        public SpinnerInfo(string userMessage, string context = "Unknown")
        {
            Context = context;
            UserMessage = userMessage;
            Timer = Stopwatch.StartNew();
            _delayTimer = new Timer(20); // threshold in ms before showing the spinner
            _delayTimer.Elapsed += AfterDelayHandler;
            _delayTimer.AutoReset = false; // Fire the event one time only
            _delayTimer.Start();
        }
    
        public void Stop()
        {
            lock (_stopLock)
            {
                Timer.Stop();
            }
        }
    
        /// <summary>
        /// When the waiting threshold has been reached, if the task
        /// is still going (i.e. the spinner should still be on the screen)
        /// then actually show the spinner
        /// </summary>
        private void AfterDelayHandler(object sender, ElapsedEventArgs e)
        {
            lock (_stopLock)
            {
                if (Timer.IsRunning) // Easy way to see if the operation is still executing
                { // Operation is still in progress
                    BTProgressHUD.Show(UserMessage, -1, ProgressHUD.MaskType.Black);
                }
                _delayTimer.Stop();
            }
        }
    
        // [IDisposable implementation that disposes of the _delayTimer]
        [...]
    }
    

    当代码请求微调器显示时,它将创建一个新的SpinnerInfo并将其添加到堆栈中。当代码希望微调器消失(长时间运行的操作完成)时,它会从堆栈Stop()中弹出它,并将信息报告为遥测。

    然而,我在lock上遇到了僵局。我添加了锁,因为我担心以下情况:

    1. 线程A启动操作和SpinnerInfo
    2. 线程B由Timer AfterDelayHandler触发,并检查微调器的秒表是否仍在运行;它是
    3. 操作停止,线程A停止微调器的秒表
    4. 线程B调用BTProgressHUD来显示微调器
    5. 然后,旋转器永远在屏幕上。

      有没有更好的方法来协调这两个线程以避免这种情况?

0 个答案:

没有答案