我在Xamarin.iOS中使用BTProgressHUD在UI上显示一个微调器。当满足以下两个条件时,我想展示微调器:
我在自定义对象中持有操作/微调器的状态:
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
上遇到了僵局。我添加了锁,因为我担心以下情况:
AfterDelayHandler
触发,并检查微调器的秒表是否仍在运行;它是然后,旋转器永远在屏幕上。
有没有更好的方法来协调这两个线程以避免这种情况?