我對有以下行爲計時器的要求:如何正確實現自定義定時在.net
- 毫秒精度
- 我想Tick事件處理程序只會被調用一次電流節拍處理已完成(很像的WinForms定時器)
- 我想在主UI線程不被線程計時器被吞噬的異常,所以這需要調用/發送,而不是的BeginInvoke /後
我玩過CreateTimerQueueTimer
,取得了一些成功,但同時在刪除定時器時遇到代碼重入和/或鎖定問題。
我決定創建自己的計時器,以便我可以更好地瞭解引擎蓋下發生了什麼,以便我可以修復鎖定和再入口問題。我的代碼似乎很好地使我相信我可以使用它。它看起來很健康嗎?
我已經放入了一個檢查計時器是否被刪除,以確保刪除完成之前,可以再次創建計時器。這看起來好嗎?
注意:我應該說,我打電話timeBeginPeriod(1)
和timeEndPeriod(1)
,以達到毫秒的準確度。
(下面的代碼是從vb.net轉換爲C#,所以對於任何道歉錯過亂七八糟起坐}
ETA:我發現了一個問題與它如果定時器的間隔運行。 1毫秒,和我打電話,說,,它鎖定了@而(this.DeleteRequest
)。這 一定是因爲TimerLoop
在this.CallbackDelegate.Invoke(null)
通話。
public class MyTimer : IDisposable
{
private System.Threading.TimerCallback CallbackDelegate;
private bool DeleteRequest;
private System.Threading.Thread MainThread;
public MyTimer(System.Threading.TimerCallback callBack)
{
this.CallbackDelegate = callBack;
}
public void Create(int interval)
{
while (this.DeleteRequest) {
System.Threading.Thread.Sleep(0);
}
if (this.MainThread != null) {
throw new Exception("");
}
this.MainThread = new System.Threading.Thread(TimerLoop);
// Make sure the thread is automatically killed when the app is closed.
this.MainThread.IsBackground = true;
this.MainThread.Start(interval);
}
public void Change(int interval)
{
// A lock required here?
if (!this.IsRunning()) {
throw new Exception("");
}
this.Delete();
this.Create(interval);
}
public void Delete()
{
this.DeleteRequest = true;
}
public bool IsRunning()
{
return (this.MainThread != null) && this.MainThread.IsAlive;
}
private void TimerLoop(object args)
{
int interval = (int)args;
Stopwatch sw = new Stopwatch();
sw.Start();
do {
if (this.DeleteRequest) {
this.MainThread = null;
this.DeleteRequest = false;
return;
}
long t1 = sw.ElapsedMilliseconds;
// I want to wait until the operation completes, so I use Invoke.
this.CallbackDelegate.Invoke(null);
if (this.DeleteRequest) {
this.MainThread = null;
this.DeleteRequest = false;
return;
}
long t2 = sw.ElapsedMilliseconds;
int temp = Convert.ToInt32(Math.Max(interval - (t2 - t1), 0));
sw.Reset();
if (temp > 0) {
System.Threading.Thread.Sleep(temp);
}
sw.Start();
} while (true);
}
// The dispose method calls this.Delete()
}
您可以嘗試發佈此[codereview.se] –
謝謝,我沒有聽說過該網站。 – Jules
「毫秒準確度」是什麼意思?調用睡眠模式將確保您的線程至少在指定的時間內沒有再次安排,但不能保證它的安排時間。 – Joe