かなり長い投稿と多くのコードについて事前にお詫び申し上げます。
私のアプリケーションには時間指定自動保存機能があります。ユーザーから、残り時間を視覚的に示すように求められました。私はカウントダウンタイマーについていくつかの調査を行い、最終的に以下のクラスを書きました:
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();
}
}
}
}
私はタイマーを使用しており、「起動」するたびにカウンターを減らします。減分ごとにイベントが開始されるため、フォームでイベントを視覚的に表示できます。カウンターがゼロに達すると、別のイベントが自動保存を開始します。
ユーザーが手動で保存した場合、または新しいプロジェクトを開いた場合に自動保存を再開できるようにするために、他にもいくつかのビットが含まれています。
それは私にとってはうまくいくようでした。ただし、ユーザーは、タイマーが長く実行されるほど、自動保存の間隔が短くなると報告しています。タイマーを毎秒刻むように設定したところ、調査の結果、タイマーが 2 倍の速度で動作することがわかりました。そのため、カウンターが 60 (秒) に設定されている場合は、30 秒ごとに実行されます。ユーザーが見た動作を再現することはできませんが、彼のログは確かに実行速度が速すぎることを示しています。
これはメインアプリと同じスレッドにあります-それは問題になる可能性があります. これまでのすべてのテストでは、ダニが 3 回ごとに 2 回連続して発火しているように見える以外は何も起きていません。
洞察力について事前に感謝します。