C # 'da bir zamanlayıcı nasıl sıfırlanır?


114

Üç vardır Timersınıflar ben farkında olduğumu, System.Threading.Timer, System.Timers.Timer, ve System.Windows.Forms.Timer, ancak bunların hiçbiri bir var .Reset()0'a akım geçen süre sıfırlanır ediyorum işlevi.

Bu işleve sahip bir BCL sınıfı var mı? Bunu yapmanın hack olmayan bir yolu var mı? (Belki de zaman sınırını değiştirmenin onu sıfırlayabileceğini düşündüm) TimerBu işleve sahip bir sınıfı yeniden uygulamanın ne kadar zor olacağını veya BCL sınıflarından biriyle nasıl güvenilir bir şekilde yapılacağını düşündünüz mü?


3
JP'nin

Bende de aynı sıfırlama ihtiyacına sahibim ve belirtilen aynı nedenlerden dolayı FileSystemWatcher tatsız ve kullanması uygun değil
John Lewin

Kronometreyi bir zamanlayıcı için kullanırsanız ve genişletme yöntemi yanıtını kullanırsanız dikkatli olun, çünkü Stopwatch.Restart genişletme yöntemi .NET 4.0'da geliyor. msdn.microsoft.com/en-us/library/…
si618

Yanıtlar:


149

Her zaman yaparım ...

myTimer.Stop();
myTimer.Start();

... bu bir hack mi? :)

Yorum başına, Threading.Timer'da, bu Change method ...

dueTime Type: System.Int32Timer oluşturulduğunda belirtilen geri çağrı yöntemini çağırmadan önce milisaniye cinsinden gecikecek süre. Timeout.InfiniteZamanlayıcının yeniden başlamasını önlemek için belirtin . Zamanlayıcıyı hemen yeniden başlatmak için sıfır (0) belirtin.


Diğer sorun, yalnızca Forms.Timer ile woeks olması ve uygulamamın hiçbir parametre içermeyen GUI (Application.Start ()) içermemesi, bu nedenle Threading.Timer sınıfının başka nedenlerden dolayı daha iyi olduğunu, ancak iyi bir nokta olduğunu düşünüyorum.
Matthew Scharley

3
@Matthew: Çeşitli zamanlayıcı sınıfları ve bunların ne zaman kullanılmasının uygun olduğu hakkında bir tartışma için msdn.microsoft.com/en-us/magazine/cc164015.aspx adresine bakın . Genel olarak, yine de, Forms.Timeryalnızca bir GUI ile kullanılmalıdır. Ancak, yanında Forms.Timerve Threading.Timerde var Timers.Timer.
Brian

60

System.Threading.Timer dışında tüm zamanlayıcılar Start () ve Stop () yöntemlerinin eşdeğerine sahiptir.

Yani ... gibi bir uzatma yöntemi

public static void Reset(this Timer timer)
{
  timer.Stop();
  timer.Start();
}

... bunu yapmanın bir yolu.


1
Geçen zamanı ölçmek istemiyorum. Bunun için benim tam kullanım durumum, bir dizini izleyen bir FileSystemWatcher'a sahip olmam ve değişiklik gruplarını yakalamak istememdir (örneğin, birbirlerinin 5'leri içinde yapılan değişiklikler). Teori, ilk değişikliğin, en sonunda grubu ateşleyip kapatana kadar her değişiklikle sıfırlanan bir zamanlayıcı başlatmasıdır.
Matthew Scharley

Evet, sorunuzu tekrar okuduğumda bunu fark ettim. Cevabımı düzenledim.
Dan

Bu işe yarar ve sadece ararsanız bunun işe yaramayacağını unutmamak önemlidir timer.Start(). Ben yapılan bu LINQPad sorgusu bunu test etmek. İçinden çıkarmayı deneyin timer.Stopve farkı göreceksiniz.
Jared Beach

30

İçin System.Timers.Timer, MSDN belgelerine göre, http://msdn.microsoft.com/en-us/library/system.timers.timer.enabled.aspx :

Zamanlayıcı başladıktan sonra aralık ayarlanırsa, sayım sıfırlanır. Örneğin, aralığı 5 saniyeye ayarlarsanız ve ardından Enabled özelliğini true olarak ayarlarsanız, sayım Enabled ayarlandığında başlar. Sayım 3 saniye olduğunda aralığı 10 saniyeye sıfırlarsanız, Elapsed olayı, Enabled öğesi true olarak ayarlandıktan 13 saniye sonra ilk kez ortaya çıkar.

Yani,

    const double TIMEOUT = 5000; // milliseconds

    aTimer = new System.Timers.Timer(TIMEOUT);
    aTimer.Start();     // timer start running

    :
    :

    aTimer.Interval = TIMEOUT;  // restart the timer

1
Buradaki sorun, zamanlayıcının zaten çalışıp çalışmadığını her zaman sıfırlamak istediğinizi bilmemenizdir. Yani, birTimer.Interval = TIMEOUT ve bir aTimer.Start () yapmanız gerekir. Yani bütün olarak, yukarıdaki bir sıfırlama işlevi daha az satır ve değişken kullanır. Yine de harika bir ek.
e-motiv

1
@ RU-Bn OP açıkça " a .Reset () fonksiyonu, geçen süreyi 0'a sıfırlayacaktır ." - zamanlayıcının çalışıp çalışmadığını bile bilmediğiniz kötü tasarlanmış bir uygulamada kullanılması amaçlandığından bahsetmez. Ayrıca yazarın yorumunu da kontrol edin (4 yıldan fazla bir süre önce): " Teori, ilk değişikliğin, sonunda ateşlenip grubu kapatana kadar her değişiklikle sıfırlanan bir zamanlayıcı başlatmasıdır. " Yine de olumsuz oy için teşekkürler.
mMontu

Ben de öyle bir problem gördüm. Yaptığım şey: aTimer.Interval = aTimer.Interval. Bu, döngünün devam ettiğini tetikledi. Beni neden yener ama işe yarıyor ...
Herman Van Der Blom

7

Reset () adında bir uzantı yöntemi yazabilirsiniz.

  • Stop () - Timers.Timer ve Forms.Timer için Start () çağırır
  • Threading.Timer için Değiştir çağırır

5

Zamanlayıcıya yeni bir değer atadım:

mytimer.Change(10000, 0); // reset to 10 seconds

benim için iyi çalışıyor.

kodun üst kısmında zamanlayıcıyı tanımlayın: System.Threading.Timer myTimer;

if (!active)
        {
            myTimer= new System.Threading.Timer(new TimerCallback(TimerProc));
        }
        myTimer.Change(10000, 0);
        active = true;

private void TimerProc(object state)
    {
        // The state object is the Timer object.
        System.Threading.Timer t = (System.Threading.Timer)state;
        t.Dispose();
        Console.WriteLine("The timer callback executes.");
        active = false;
        //action to do when timer is back to zero
    }

5

Kullanırken Anlaşılır olması için diğer bazı yorum, yanlıştır çünkü System.Timerstrue Etkin ayarı olacaktır Geçen süreyi sıfırlamak. Davranışı sadece aşağıdakilerle test ettim:

Timer countDown= new Timer(3000);

Main()
{
    TextBox.TextDidChange += TextBox_TextDidChange;
    countdown.Elapsed += CountDown_Elapsed;
}

void TextBox_TextDidChange(Object sender, EventArgs e)
{
    countdown.Enabled = true;
}

void CountDown_Elapsed(object sender, EventArgs e)
{
    System.Console.WriteLine("Elapsed");
}

Metin kutusuna tekrar tekrar metin giriyordum ve zamanlayıcı yalnızca son tuş vuruşundan 3 saniye sonra çalışıyordu. Göreceğiniz gibi dokümanlarda da ipucu verilmiştir: çağrı Timers.Start()basitçe Enabled'ı true olarak ayarlar.

Ve emin olmak için, en başından beri doğrudan gitmeliydim, .NET referans kaynağında , zaten Etkinleştirilmiş bir zamanlayıcıyı etkinleştirirseniz UpdateTimer(), dahili olarak çağıran özel yöntemi çağırdığını göreceksiniz Change().


Hayır, sen hatalısın. Özel UpdateTtimeryöntem, yalnızca ve yalnızca geçerli değeri Enabledyeniye eşit değilse çağrılır value.
Nicolò Carandini

3

Bir Zamanlayıcı için (System.Windows.Forms.Timer).

.Stop, ardından .Start yöntemleri sıfırlama olarak çalıştı.


1

Windows.timer'ı sıfırlamanın diğer bir alternatif yolu, aşağıdaki gibi sayacı kullanmaktır:

int tmrCtr = 0;
Timer mTimer;

private void ResetTimer()
{
  tmrCtr = 0;
}

private void mTimer_Tick()
{
  tmrCtr++;
  //perform task
}  

Dolayısıyla, her 1 saniyede bir tekrarlamayı düşünüyorsanız, zamanlayıcı aralığını 100 ms olarak ayarlayabilir ve sayacı 10 döngü olarak test edebilirsiniz.

Bu, zamanlayıcının farklı zaman dilimlerinde sona erebilecek bazı işlemler için beklemesi gerekiyorsa uygundur.


1

bunu yaparım

//Restart the timer
queueTimer.Enabled = true;

Bu sadece onu mümkün kılar. Önceden devre dışı bırakılmış olsa bile, yeniden etkinleştirmek o noktaya kadar toplanan geçen süreyi değiştirmez.
vapcguy

Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.