Thread Con Timer Interno.

venerdì 08 febbraio 2013 - 17.47
Tag Elenco Tags  C#  |  .NET 1.0  |  .NET 1.1  |  .NET 2.0  |  .NET 3.0  |  .NET 3.5  |  .NET 4.0  |  Visual Studio 2010  |  Visual Studio 2008  |  Visual Studio 2005

a.malisani Profilo | Newbie

Salve,
mi sono cimentato a lavorare per la prima volta con i Thread.
Ho una consolle application che instanzia dei thread, i quali interrogano a intervalli di x secondi uno specifico web service.
Il mio problema è che l’applicazione giustamente si chiude immediatamente, in quanto nel metodo Run() del thread eseguo solo lo Start() del timer. A questo punto i therad sono “stopped” e l’applicazione si chiude.
Se nel main della consolle poco elegantemente metto un while (true){sleep(1000)} allora l’applicazione rimane viva e il timer nei thread scatta correttamente.
In che modo si risolve correttametne questo problema?

Grazie!

Alessandro

Developer .NET

0v3rCl0ck Profilo | Guru

Ciao Alessandro,

il tuo caso è molto semplice, un qualsiasi programma conta sempre di un entry-point, cioè un metodo che viene eseguito come funzione main dell'applicazione, e nella maggior parte dei casi se un metodo main si conclude, anche l'applicazione/processo/domain ad esso connesso si chiude, nel tuo caso appunto la console ha la sua funzione main, e per tenere in vita eventuali thread in esecuzione, devi per forza tenere in vita il processo che li hosta e di conseguenza la tua console application, per fare questo in una console app di solito si rimane in attesa di un input da parte dell'utente prima di chiudere l'applicazione:

Console.WriteLine("Premi ENTER per chiudere l'applicazione...");
Console.ReadLine();

vorrei aggiungere solo una cosa che magari non sai, un System.Timers.Timer (http://msdn.microsoft.com/en-us/library/system.timers.timer(v=vs.100).aspx) di default già utilizza uno o più thread quando esegue la callback Elapsed (If the SynchronizingObject property is null, the Elapsed event is raised on a ThreadPool thread.), quindi un timer startato nella main della console app non bloccherà mai l'esecuzione del programma. Se apri il link msdn vedrai che c'è proprio un esempio al tuo caso, crea un timer, lo inizializza, lo avvia e subito dopo mette la console in attesa di input da parte dell'utente, proprio per non fare chiudere subito l'applicazione.

using System; using System.Timers; public class Timer1 { private static System.Timers.Timer aTimer; public static void Main() { // Normally, the timer is declared at the class level, // so that it stays in scope as long as it is needed. // If the timer is declared in a long-running method, // KeepAlive must be used to prevent the JIT compiler // from allowing aggressive garbage collection to occur // before the method ends. You can experiment with this // by commenting out the class-level declaration and // uncommenting the declaration below; then uncomment // the GC.KeepAlive(aTimer) at the end of the method. //System.Timers.Timer aTimer; // Create a timer with a ten second interval. aTimer = new System.Timers.Timer(10000); // Hook up the Elapsed event for the timer. aTimer.Elapsed += new ElapsedEventHandler(OnTimedEvent); // Set the Interval to 2 seconds (2000 milliseconds). aTimer.Interval = 2000; aTimer.Enabled = true; Console.WriteLine("Press the Enter key to exit the program."); Console.ReadLine(); // If the timer is declared in a long-running method, use // KeepAlive to prevent garbage collection from occurring // before the method ends. //GC.KeepAlive(aTimer); } // Specify what you want to happen when the Elapsed event is // raised. private static void OnTimedEvent(object source, ElapsedEventArgs e) { Console.WriteLine("The Elapsed event was raised at {0}", e.SignalTime); } }


Ciao!
----------------------------------------------
Michael Denny
Lead Software Developer & Solutions Architect
Microsoft Framework (C# ASP.NET VB.NET)
http://blogs.dotnethell.it/Regulator/

a.malisani Profilo | Newbie

Grazie, ottima spiegazione.
Per quanto riguarda lo stato stopped del thread... non mi resta che fare un ciclo all'interno del metodo start() fintanto che una proprieta non lo fà uscire dal loop...
Alessandro

Developer .NET

0v3rCl0ck Profilo | Guru

Perchè devi fare un ciclo nel thread? se metti la console in read Console.ReadLine(), il thread non va in stopped di se, al più andrà in stopped se appunto il metodo main del thread (il delegato passato al costruttore) si chiude perchè l'operazione che fa è solo quella di mettere in start un timer che appunto non è un operazione bloccante perchè a sua volta alza un nuovo thread. Se nel thread fai solo lo start del timer, a questo punto non ti server, tanto vale che fai semplicemente lo start dal main della console.

Ad ogni modo se devi sincronizzarti ad un altro thread/processo ti consiglio di dare un occhio a tutti i tipi di WaitHandle che fanno appunto parte del namespace System.Threading, ad esempio l'AutoResetEvent o ManualResetEventSlim (http://msdn.microsoft.com/en-us/library/system.threading.manualreseteventslim.aspx) e questo potrebbe essere un esempio (non prendere questo codice come buon design, è solo per farti capire le potenzialità degli oggetti di sincronizzazione, che evitano di farti fare cicli infiniti e che servono appunto per sincronizzare thread diversi e/o processi):

Il codice sorgente non è stato renderizzato qui
perchè non c'è sufficiente spazio.
Clicca qui per visualizzarlo in una nuova finestra
-------------------------------------------------------
Michael Denny
Lead Software Developer & Solutions Architect
http://blogs.dotnethell.it/Regulator/
Partecipa anche tu! Registrati!
Hai bisogno di aiuto ?
Perchè non ti registri subito?

Dopo esserti registrato potrai chiedere
aiuto sul nostro Forum oppure aiutare gli altri

Consulta le Stanze disponibili.

Registrati ora !
Copyright © dotNetHell.it 2002-2024
Running on Windows Server 2008 R2 Standard, SQL Server 2012 & ASP.NET 3.5