2012-03-05 66 views
9

Rozumiem, że w usłudze Windows lepiej jest używać Timer niż Thread.Sleep(timeout). Jednak we wszystkich przykładach kodu, które mogłem znaleźć w Internecie, który obsługiwał pracowników Azure, jest to Thread.Sleep(timeout), które jest używane zamiast Timer.Korzystanie z Thread.Sleep lub Timer w roli robotów Azure w .NET?

Nawet domyślny kod podany w szablonie projektu Pracownik w Visual Studio używa Thread.Sleep:

public class WorkerRole : RoleEntryPoint 
{ 
    public override void Run() 
    { 
     // This is a sample worker implementation. Replace with your logic. 
     Trace.WriteLine("$projectname$ entry point called", "Information"); 

     while (true) 
     { 
      Thread.Sleep(10000); 
      Trace.WriteLine("Working", "Information"); 
     } 
    } 
// ... 
} 

Dotychczas byłem również używając Thread.Sleep w moich pracowników, ale nie rozumiejąc dlaczego. Moje pytanie brzmi: dlaczego używać Thread.Sleep(timeout) w roli robota Azure zamiast Timer? Jaka jest różnica między usługą Windows a robotami platformy Azure, która prowadzi do tej różnicy w sposobie, w jaki powinniśmy wyobrazić sobie taką aplikację? Czy korzystanie z Timer w usłudze Azure jest dobre czy złe?

Wszelkie wyjaśnienia z linkami do niektórych zasobów wyjaśniających podstawy tego są mile widziane, ponieważ nie udało mi się znaleźć niczego na razie.

+0

To naprawdę nie jest pytanie specyficzne dla Windows Azure. Istnieje [świetna odpowiedź StackOverflow] (http://stackoverflow.com/questions/2822441/system-timers-timer-threading-timer-vs-thread-with-whileloop-thread-sleep-for), która idzie w całkiem sporo szczegółów na temat różnych timerów. Dotyczy to również maszyn wirtualnych systemu Windows Azure, ponieważ są to maszyny wirtualne z systemem Windows Server 2008. –

+0

Dzięki za link. To interesujące, ale nie mam wrażenia, że ​​to naprawdę odpowiada na moje pytanie. Rozumiem, że Windows Azure to również maszyny wirtualne, ale jeśli to była VM, to dlaczego nie korzystać z usług Windows? W takim przypadku moje pytanie nie musiałoby być takie. – Guillaume

+0

Ah ... Cóż, możesz oczywiście korzystać z usług Windows. Aby jednak korzystać z usługi systemu Windows w systemie Windows Azure, należy wykonać pewne czynności. Oto [blog] (http://blogs.msdn.com/b/mwasham/archive/2011/03/30/migrating-a-windows-service-to-windows-azure.aspx) pokazujący, o co chodzi. O wiele łatwiej jest uruchomić kod w ramach zdarzeń dostarczanych przez pracownika Windows Azure lub rolę sieci Web. Zobacz moją [odpowiedź na ten temat] (http://serverfault.com/a/365054/99269) również na ServerFault. –

Odpowiedz

15

Celem pętli Thread.Sleep() jest zamknięcie metody Run(). Jeśli wyjdzie Run(), twój robot zostanie uruchomiony ponownie. Nie wiem, czy udało ci się skutecznie osiągnąć ten cel dzięki Timerowi.

Najprawdopodobniej twój procesor marnuje trochę czasu, aby obudzić ten wątek co 1000 msek, aby nic nie robić. Wątpię, żeby to było znaczące, ale mnie też to podsłuchało. Moim rozwiązaniem było czekać zamiast tego na Token Anulowania.

public class WorkerRole : RoleEntryPoint { 
    CancellationTokenSource cancelSource = new CancellationTokenSource(); 

    public override void Run() 
    { 
     //do stuff 
     cancelSource.Token.WaitHandle.WaitOne(); 
    } 

    public override void OnStop() 
    { 
     cancelSource.Cancel(); 
    } 
} 

To utrzymuje metodę run() z wyjściem bez marnowania czasu procesora na ruchliwej oczekiwania. Możesz również użyć Tonu anulowania w innym miejscu w programie, aby zainicjować inne operacje wyłączania, które możesz wykonać.

+0

Masz na myśli, że nawet jeśli mam programator, który jest ustawiony jako statyczne pole mojej klasy 'WorkerRole' i jego wydarzenie' Elapsed' ma przypisaną do niego metodę, wątek będzie nadal kończyć się po przetworzeniu metody 'Run()' ? – Guillaume

+1

Tak, tak mówi dokumentacja. Jeśli spróbujesz, najprawdopodobniej Twoja rola będzie ciągle uruchamiana, zamykana i restartowana. http://msdn.microsoft.com/en-us/library/windowsazure/microsoft.windowsazure.serviceruntime.roleentrypoint.run.aspx –

+2

W jaki sposób rozwiązanie "Thread.Sleep (Timeout.Infinity)" zestawia się z oczekiwaniem na "WaitHandle"? I o to chodzi, dlaczego nie po prostu użyć "ManualResetEvent"? To więcej niż prawdopodobne to samo. – casperOne

-2

Thread.Sleep to dosłownie marnowanie czasu procesora. Twój wątek jest zablokowany i chociaż CPU nic nie robi, nie może go użyć w innych wątkach. Nie jestem zaznajomiony z modelem cenowym Azure, ale możesz być potencjalnie obciążony za ten czas, ponieważ używał go twój wątek:

Tak więc zawsze należy używać go do każdego rodzaju pauzy.

W przykładowych przykładach kodowania zazwyczaj używa się Thread.Sleep dla uproszczenia.

+0

M $ opłata za nic nie robić? Wspaniale - chciałbym móc temu uciec! –

+7

@Martin - Microsoft pobiera opłaty za korzystanie z zasobów. Możesz uruchomić swoją maszynę wirtualną na 0% lub 100% CPU przez cały dzień - Twoje połączenie. Płacisz za rdzeń za godzinę. Podobnie jak w przypadku wynajmowania pokoju hotelowego: płacisz, niezależnie od tego, czy bierzesz udział w imprezie czy nie. –

+0

Tak naprawdę, to nie tylko przykłady kodu, które znalazłem, które używają 'Thread.Sleep'. Nawet domyślny kod podany w szablonie Worker podczas tworzenia nowego projektu Worker używa "Thread.Sleep". – Guillaume

Powiązane problemy