2011-01-13 14 views
6

Mam dwie alternatywy przy użyciu timera lub korzystając spać, muszę wywołać metodę co 3 sekundy po tym metoda jest zakończona, pisałem podstawowy przykład wykazać, co mam na myśli:Co powinienem użyć uśpienia lub czasomierza

public static void Main() 
{ 
    new Thread(new ThreadStart(fooUsingSleep)).Start(); 

    callToMethodAfterInterval(new Action<object, ElapsedEventArgs>(fooUsingTimer), 3000); 
} 

public static void fooUsingSleep() 
{ 
    Console.WriteLine("Doing some consuming time work using sleep"); 
    Thread.Sleep(3000); 
    fooUsingSleep(); 
} 

public static void fooUsingTimer(object dummy, ElapsedEventArgs dummyElapsed) 
{ 
    Console.WriteLine("Doing some consuming time work usning timer"); 
    callToMethodAfterInterval(new Action<object, ElapsedEventArgs>(fooUsingTimer), 3000); 
} 

public static void callToMethodAfterInterval(Action<object,ElapsedEventArgs> inMethod, int inInterval) 
{ 
    System.Timers.Timer myTimer = new System.Timers.Timer(); 
    myTimer.Elapsed += new ElapsedEventHandler(inMethod); 
    myTimer.Interval = inInterval; 
    myTimer.AutoReset = false; 
    myTimer.Start(); 
} 

Moje pytania to

1) Czy mogę napisać kod z zegarem bardziej eleganckim? Oznacza usunięcie wywołania metody callToMethodAfterInterval z fooUsingTimer, uczynienie z timera jednej lub dwóch linii i usunięcie zmiennych fikcyjnych z deklaracji fooUsingTimer?

2) Rozumiem, że sen nie jest zajęty oczekiwaniem (http://www.codeproject.com/KB/threads/ThreadingDotNet.aspx) Nie znalazłem więc uzasadnienia, aby użyć opcji licznika czasu, ponieważ sen jest prostszy, a co lepiej zastosować, wersję timera lub sypialną?

3) Wiem, że Timers.timer jest bezpieczny dla wątków, czy może mi pomóc w zachowaniu, które chcę zaimplementować?

Dzięki.

Odpowiedz

2

Prawdziwy kontekst programu liczy też.

Opcja uśpienia "marnuje" wątek, nie stanowi problemu w małej aplikacji konsolowej, ale ogólnie nie jest dobrym pomysłem.

Nie trzeba ponownie uruchomić stoper dodaje zachowa Tkanina:

static void Main(string[] args) 
    { 
     var t = new System.Timers.Timer(1000); 
     t.Elapsed += (s, e) => CallMeBack(); 
     t.Start(); 

     Console.ReadLine(); 
    } 
+1

Chciałbym zauważyć, że nie sądzę, że jest to dokładnie to, co pierwotnie zamierzał zrobić oryginał - to było wykonywanie długiego zadania, a następnie ponowne uruchamianie go 3 sekundy po zakończeniu - twój będzie działał co sekundę? – Paddy

+0

@Paddy, tak, zakładałem stosunkowo krótkie zadanie. PO powinien powiedzieć. –

+0

Nie chcę foo opcja zostanie wezwany przed innych połączeń do foo ma gotowych .. – Delashmate

0

Uśpienie wystarczy, zegar z drugiej strony został zaprojektowany do tego celu, konwencje są lepsze i zazwyczaj sprawiają, że kod jest bardziej zrozumiały.

+0

Jak mogę napisać część timera bardziej elegancki? – Delashmate

3

Czy zdajesz sobie sprawę, że fooUsingSleep dzwoni się w kółko? W końcu wygeneruje przepełnienie stosu.

Jeśli używasz timera, może być tak proste, jak to:

System.Windows.Forms.Timer t = new System.Windows.Forms.Timer(); 
    t.Interval = 3000; 
    t.Tick += new EventHandler((o,ea) => Console.WriteLine("foo")); 
+0

+1 eleganckie rozwiązanie, w jaki sposób może to spowodować przepełnienie stosu? Nie widzę tego, w twoim rozwiązaniu metoda może zostać wywołana zanim ostatnia się zakończy i może prowadzić do znalezienia poważnych błędów, więc tego powodu nie zaznaczyłem jako odpowiedź – Delashmate

+1

nie można jej nazwać przed ostatnim zakończył się, ponieważ działają w tym samym wątku. Rozwiązanie (wywołanie fooUsingSleep() od wewnątrz fooUsingSleep() będzie ostatecznie przepełnienia stosu, ponieważ na każdej metody zadzwonić kontekst wykonanie jest popychany na stos, który nie ma nieograniczonej pojemności) – Axarydax

+0

Ok, teraz rozumiem przepełnienie stosu można wymienić:) – Delashmate

Powiązane problemy