2012-03-05 8 views
9

Capisco che in un servizio di Windows, è meglio utilizzare Timer anziché Thread.Sleep(timeout). Tuttavia, in tutti gli esempi di codice che è possibile trovare su Internet che gestiscono i lavoratori di Azure, è Thread.Sleep(timeout) che viene utilizzato al posto di Timer.Utilizzo di Thread.Sleep o Timer nel ruolo di lavoro di Azure in .NET?

Anche il codice di default fornito nel modello di progetto Lavoratore in Visual Studio utilizza un 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"); 
     } 
    } 
// ... 
} 

Finora, ho anche utilizzando Thread.Sleep nei miei lavoratori, ma senza realmente capire il perché. Quindi la mia domanda è: perché utilizzare Thread.Sleep(timeout) nel ruolo di lavoro di Azure anziché Timer? Qual è la differenza tra il servizio Windows e il lavoratore di Azure che porta a questa differenza nel modo in cui dovremmo concepire questo tipo di applicazione? È utile o meno usare Timer nei lavoratori di Azure?

Qualsiasi spiegazione con collegamenti ad alcune risorse che spiegano i fondamenti di questo è la benvenuta in quanto non ho trovato nulla finora.

+0

Questa non è una domanda specifica di Windows Azure. C'è una [ottima risposta StackOverflow] (http://stackoverflow.com/questions/2822441/system-timers-timer-threading-tims-vs-thread-with-whileloop-thread-sleep-for) che va un bel po ' di dettagli sui diversi timer. Questo vale anche per le macchine virtuali Windows Azure, dal momento che sono VM di Windows Server 2008. –

+0

Grazie per il link. È interessante ma non mi sembra che risponda davvero alla mia domanda. Capisco che Windows Azure sia anche VM, ma se fosse _just_ VM, perché non usare solo i servizi di Windows? In tal caso, la mia domanda non sarebbe necessaria. – Guillaume

+0

Ah ... Beh, puoi certamente usare i servizi di Windows. Tuttavia, per utilizzare un servizio Windows in Windows Azure, è necessario lavorare. Ecco un [post di blog] (http://blogs.msdn.com/b/mwasham/archive/2011/03/30/migrating-a-windows-service-to-windows-azure.aspx) che mostra cosa è coinvolto. È molto più semplice eseguire il codice all'interno degli eventi forniti da un Windows Azure Worker o da un ruolo Web. Vedere anche la mia [risposta a questo] (http://serverfault.com/a/365054/99269) su ServerFault. –

risposta

15

Lo scopo del ciclo Thread.Sleep() è quello di impedire l'uscita del metodo Run(). Se Run() termina, il lavoratore verrà riavviato. Non so che si possa raggiungere questo obiettivo in modo efficace con un timer.

Molto probabilmente la tua CPU sta sprecando un po 'di tempo per risvegliare quel thread ogni 1000 msec per non fare nulla. Dubito che sia significativo, ma mi ha infastidito. La mia soluzione era invece aspettare un CancellationToken.

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

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

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

Ciò impedisce al metodo Run() di uscire senza sprecare tempo CPU in attesa. È inoltre possibile utilizzare il metodo CancellationToken in altre parti del programma per avviare qualsiasi altra operazione di arresto che potrebbe essere necessario eseguire.

+0

Vuoi dire che anche se ho un Timer che è impostato come un campo statico della mia classe 'WorkerRole' e il suo evento' Elapsed' ha un metodo assegnato, il thread uscirà ancora una volta che il metodo 'Run()' viene elaborato ? – Guillaume

+1

Sì, questo è ciò che dice la documentazione. Se lo provi, molto probabilmente vedrai il tuo ruolo avviarsi, spegnersi e riavviarsi continuamente. http://msdn.microsoft.com/en-us/library/windowsazure/microsoft.windowsazure.serviceruntime.roleentrypoint.run.aspx –

+2

Come si accumula la soluzione 'Thread.Sleep (Timeout.Infinity)' in attesa sul 'WaitHandle'? E del resto, perché non usare semplicemente un 'ManualResetEvent'? È più che probabile la stessa cosa. – casperOne

-2

Thread.Sleep è letteralmente uno spreco di tempo del processore. La tua discussione è bloccata e anche se la CPU non sta facendo nulla, non può essere utilizzata da altri thread. Non ho familiarità con il modello di prezzo di Azure, ma potresti essere potenzialmente addebitato per questa volta, perché il tuo thread lo utilizza :)

Quindi Timer deve essere sempre utilizzato per qualsiasi tipo di pausa.

Gli esempi di codice di solito utilizzano Thread.Sleep per la semplicità.

+0

M $ addebitati per non aver fatto nulla? Fantastico - Vorrei poterlo fare franca! –

+7

@ Martin - Microsoft addebita l'utilizzo delle risorse. Puoi eseguire la tua VM a 0% o 100% CPU tutto il giorno - la tua chiamata. Paghi per core all'ora. Proprio come affittare una stanza d'albergo: paghi se ci stai organizzando una festa o lontano da essa. –

+0

Beh, in realtà, non sono solo gli esempi di codice che ho trovato che usano 'Thread.Sleep'. Anche il codice predefinito fornito dal modello Worker quando si crea un nuovo progetto Worker utilizza un 'Thread.Sleep'. – Guillaume