對於相當長的帖子和大量代碼,事先抱歉。倒數計時器的奇行爲
我的應用程序有一個定時自動保存功能。用戶要求我提供剩餘時間的視覺指標。我做了倒計時定時器一些研究,並最終寫了下面的類:
public class CountDownTimer
{
private Timer timer;
private int remaining;
////////////////////////////////////////////////////////////////////////////////////////////////////
/// <summary> Count down ticked delegate. </summary>
///
/// <remarks> Jon, 18/06/2012. </remarks>
///
/// <param name="remaining"> The remaining. </param>
/// <param name="maximum"> The maximum. </param>
////////////////////////////////////////////////////////////////////////////////////////////////////
public delegate void CountDownTickedDelegate(int remaining, int maximum);
/// <summary> Event queue for all listeners interested in Ticked event. </summary>
public event CountDownTickedDelegate Ticked;
////////////////////////////////////////////////////////////////////////////////////////////////////
/// <summary> Count down percent delegate. </summary>
///
/// <remarks> Jon, 18/06/2012. </remarks>
///
/// <param name="percent"> The percent. </param>
////////////////////////////////////////////////////////////////////////////////////////////////////
public delegate void CountDownPercentDelegate(int percent);
/// <summary> Event queue for all listeners interested in Percent events. </summary>
public event CountDownPercentDelegate Percent;
////////////////////////////////////////////////////////////////////////////////////////////////////
/// <summary> Count down done delegate. </summary>
///
/// <remarks> Jon, 18/06/2012. </remarks>
////////////////////////////////////////////////////////////////////////////////////////////////////
public delegate void CountDownDoneDelegate();
/// <summary> Event queue for all listeners interested in Done events. </summary>
public event CountDownDoneDelegate Done;
////////////////////////////////////////////////////////////////////////////////////////////////////
/// <summary> Gets or sets the maximum value to count down from </summary>
///
/// <value> The maximum value. </value>
////////////////////////////////////////////////////////////////////////////////////////////////////
public int Maximum
{
get;
set;
}
////////////////////////////////////////////////////////////////////////////////////////////////////
/// <summary> Gets or sets a value indicating whether the timer is Paused. </summary>
///
/// <value> true if paused, false if not. </value>
////////////////////////////////////////////////////////////////////////////////////////////////////
public bool Paused
{
get;
set;
}
////////////////////////////////////////////////////////////////////////////////////////////////////
/// <summary> Starts this CountDownTimer. </summary>
///
/// <remarks> Jon, 18/06/2012. </remarks>
////////////////////////////////////////////////////////////////////////////////////////////////////
public void Start()
{
timer = new Timer {
Interval = 1000
};
timer.Tick += onTimerTick;
timer.Enabled = true;
remaining = Maximum;
Paused = false;
}
////////////////////////////////////////////////////////////////////////////////////////////////////
/// <summary> Stops this CountDownTimer. </summary>
///
/// <remarks> Jon, 18/06/2012. </remarks>
////////////////////////////////////////////////////////////////////////////////////////////////////
public void Stop()
{
if (timer == null)
{
return;
}
Paused = true;
timer.Enabled = false;
timer = null;
if (Percent != null)
{
Percent(100);
}
}
////////////////////////////////////////////////////////////////////////////////////////////////////
/// <summary> Resets and restarts this CountDownTimer. </summary>
///
/// <remarks> Jon, 18/06/2012. </remarks>
////////////////////////////////////////////////////////////////////////////////////////////////////
public void Reset()
{
Stop();
Start();
}
////////////////////////////////////////////////////////////////////////////////////////////////////
/// <summary> Handles the timer tick event. </summary>
///
/// <remarks> Jon, 18/06/2012. </remarks>
///
/// <param name="sender"> Source of the event. </param>
/// <param name="e"> Event information to send to registered event handlers. </param>
////////////////////////////////////////////////////////////////////////////////////////////////////
private void onTimerTick(object sender, EventArgs e)
{
if (remaining > 0)
{
if (Ticked != null)
{
Ticked(remaining, Maximum);
}
if (Percent != null)
{
int percent = remaining * 100/Maximum;
Percent(percent);
}
if (!Paused)
{
remaining--;
}
else
{
remaining = Maximum;
}
}
else
{
Stop();
if (Done != null)
{
Done();
}
}
}
}
我使用的是定時器和每次「火患」我遞減計數器時間。每個減量都會啓動一個事件,以便我的窗體可以直觀地顯示它。當計數器達到零時,另一個事件啓動自動保存。
還有一些其他位允許自動保存如果用戶手動保存或打開新項目時重新啓動。
它似乎爲我工作。但是,用戶報告計時器運行時間越長,自動保存間隔越短。我將計時器設置爲每秒鐘打勾,我的調查顯示它以兩倍的速度運行。因此,如果計數器設置爲60(秒),那麼它每30次運行一次。我無法複製用戶看到的行爲,但他的日誌肯定顯示運行速度太快。
這與主應用程序在同一線程中 - 這可能是一個問題。迄今爲止,我所有的測試都沒有改變任何東西,除了蜱似乎每三次都會連續兩次發射。
非常感謝您的任何見解。
可能是。我現在要檢查一下。 – ScruffyDuck 2012-07-11 11:40:31
你是對的。我調用Start()比Stop()更多次我在Stop()中刪除了onTimerTick處理程序,並將Start()添加到Start()。現在廣告作品。非常感謝 – ScruffyDuck 2012-07-11 12:20:55