C# - Thread
Proprietà del thread corrente
• In questo esempio e nei successivi, aggiungere lo spazio dei nomi 'System.Threading'.
• Alcune proprietà del thread corrente:
Thread t = Thread.CurrentThread;
// Il nome del thread può essere impostato
t.Name = "Test thread";
Console.WriteLine("Thread Name: {0}", t.Name);
Console.WriteLine("Thread IsAlive: {0}", t.IsAlive);
Console.WriteLine("Thread Priority: {0}", t.Priority);
Console.WriteLine("Context ID: {0}", Thread.CurrentContext.ContextID);
Console.WriteLine("Current application domain: {0}", Thread.GetDomain().FriendlyName);
Creazione di un thread con un delegato
• Il costruttore del thread, può accettare come parametro un delegato.
• Nell'esempio, vengono creati due thread e avviati con il metodo Start() mentre l'esecuzione del programma continua. Non c'è nessuna certezza sull'ordine di scrittura sulla console. È il sistema operativo che di volta in volta decide quale thread (il principale e i due secondari) scriveranno nella console.
static void Main(string[] args)
{
Thread t1 = new Thread(threadSecondario);
t1.Start();
Thread t2 = new Thread(threadSecondario);
t2.Start();
Console.WriteLine("Thread principale (Main)");
Console.ReadKey();
}
static void threadSecondario()
{
Console.WriteLine("Thread secondario");
}
Thread background e foreground
• I thread sono foreground (in primo piano) o background (in sfondo).
• Una applicazione rimane in esecuzione finché c'è almeno un thread foreground in esecuzione (anche se il Main() termina, l'applicazione rimane in esecuzione fino al termine dell'ultimo thread foreground).
• Per impostare il tipo di thread, utilizzare la proprietà IsBackground (di default è false).
• Nell'esempio seguente, il programma termina solo quando il thread secondario termina.
static void Main(string[] args)
{
Thread t1 = new Thread(threadSecondario);
t1.IsBackground = false;
t1.Start();
Console.WriteLine("Fine Thread principale (Main)");
}
static void threadSecondario()
{
Console.WriteLine("Inizio Thread secondario");
Thread.Sleep(2000);
Console.WriteLine("Fine Thread secondario");
}
• Se viene modificata la riga 't1.IsBackground = false;' impostando 't1.IsBackground = true;', allora il programma terminerà non appena viene scritta la console dal thread principale, senza attendere il termine dei thread secondario.
Attendere che un thread finisca
• Utilizzare il metodo Join() sul thread che deve essere finito prima di continuare l’esecuzione del programma chiamante. Join() accetta anche un tempo limite di attesa e restituisce un booleano indicante se il thread è terminato oppure se è il time out è scaduto prima del termine del thread.
• Nell’esempio seguente il tre thread ‘tx’, ‘ty’ e ‘tz’ vengono eseguiti uno di seguito all’altro. Rimuovendo le istruzioni con il ‘Join()’ i thread verranno eseguiti in concorrenza.
static void Main(string[] args)
{
Thread tx = new Thread(WriteX);
Thread ty = new Thread(WriteY);
Thread tz = new Thread(WriteZ);
tx.Start();
tx.Join();
ty.Start();
ty.Join();
tz.Start();
tz.Join();
// Il thread principale non fa niente
Thread.Sleep(5000);
Console.ReadKey();
}
static void WriteX()
{
for (int i = 0; i < 100; i++)
{
Console.WriteLine("x");
}
}
static void WriteY()
{
for (int i = 0; i < 100; i++)
{
Console.WriteLine(" y");
}
}
static void WriteZ()
{
for (int i = 0; i < 100; i++)
{
Console.WriteLine(" z");
}
}
Bloccare un thread
• Per bloccare un thread per un certo tempo o finché avvengano certe condizioni, utilizzare il metodo Sleep().
• Esempio:
// Programma principale: crea ed esegue un Thread
Thread t1 = new Thread(threadSecondario);
t1.Start();
private void threadSecondario()
{
DateTime d = DateTime.Now;
d = d.AddSeconds(5);
while (DateTime.Now < d)
{
Thread.Sleep(100);
}
MessageBox.Show("Thread secondario");
}
• In questo modo la CPU non sarà caricata di lavoro inutile; togliendo la riga ‘Thread.Sleep(100);’ il programma funzionerà lo stesso, ma la CPU sarà sovraccaricata durante l’esecuzione del ciclo ‘while’.
Priorità di un thread
• La proprietà ThreadPriority è utilizzata per impostare la priorità di esecuzione di un thread. I valori di priorità sono in ordine cresecente: Lowest, BelowNormal, Normal, AboveNormal, Highest.
• Esempio:
// Programma principale: crea ed esegue un Thread
Thread t1 = new Thread(threadSecondario);
t1.Priority = ThreadPriority.Lowest;
t1.Start();
private static void threadSecondario()
{
...
}