Condividi tramite


Sospensione e interruzione dei thread

I modi più comuni per sincronizzare le attività dei thread sono bloccare e rilasciare thread o bloccare oggetti o aree di codice. Per ulteriori informazioni su questi meccanismi di locking e blocco, vedere Panoramica delle primitive di sincronizzazione.

È anche possibile fare in modo che i thread si addormentino. Quando i thread vengono bloccati o sono in stato di sospensione, è possibile usare un ThreadInterruptedException per sbloccarli dai loro stati di attesa.

Metodo Thread.Sleep

La chiamata al Thread.Sleep metodo fa sì che il thread corrente blocchi immediatamente per il numero di millisecondi o l'intervallo di tempo passato al metodo e restituisce il resto della sezione temporale a un altro thread. Una volta trascorso l'intervallo, il thread in sospensione riprende l'esecuzione.

Un thread non può chiamare Thread.Sleep su un altro thread. Thread.Sleep è un metodo statico che determina sempre la sospensione del thread corrente.

La chiamata Thread.Sleep con un valore di Timeout.Infinite fa sì che un thread venga sospeso fino a quando non viene interrotto da un altro thread che chiama il Thread.Interrupt metodo sul thread in sospensione o fino a quando non viene terminato da una chiamata al relativo Thread.Abort metodo. Nell'esempio seguente vengono illustrati entrambi i metodi di interruzione di un thread in sospensione.

using System;
using System.Threading;

public class Example
{
   public static void Main()
   {
      // Interrupt a sleeping thread.
      var sleepingThread = new Thread(Example.SleepIndefinitely);
      sleepingThread.Name = "Sleeping";
      sleepingThread.Start();
      Thread.Sleep(2000);
      sleepingThread.Interrupt();

      Thread.Sleep(1000);

      sleepingThread = new Thread(Example.SleepIndefinitely);
      sleepingThread.Name = "Sleeping2";
      sleepingThread.Start();
      Thread.Sleep(2000);
      sleepingThread.Abort();
   }

   private static void SleepIndefinitely()
   {
      Console.WriteLine($"Thread '{Thread.CurrentThread.Name}' about to sleep indefinitely.");
      try {
         Thread.Sleep(Timeout.Infinite);
      }
      catch (ThreadInterruptedException) {
         Console.WriteLine($"Thread '{Thread.CurrentThread.Name}' awoken.");
      }
      catch (ThreadAbortException) {
         Console.WriteLine($"Thread '{Thread.CurrentThread.Name}' aborted.");
      }
      finally
      {
         Console.WriteLine($"Thread '{Thread.CurrentThread.Name}' executing finally block.");
      }
      Console.WriteLine($"Thread '{Thread.CurrentThread.Name} finishing normal execution.");
      Console.WriteLine();
   }
}
// The example displays the following output:
//       Thread 'Sleeping' about to sleep indefinitely.
//       Thread 'Sleeping' awoken.
//       Thread 'Sleeping' executing finally block.
//       Thread 'Sleeping finishing normal execution.
//
//       Thread 'Sleeping2' about to sleep indefinitely.
//       Thread 'Sleeping2' aborted.
//       Thread 'Sleeping2' executing finally block.
Imports System.Threading

Module Example
    Public Sub Main()
        ' Interrupt a sleeping thread. 
        Dim sleepingThread = New Thread(AddressOf Example.SleepIndefinitely)
        sleepingThread.Name = "Sleeping"
        sleepingThread.Start()
        Thread.Sleep(2000)
        sleepingThread.Interrupt()

        Thread.Sleep(1000)

        sleepingThread = New Thread(AddressOf Example.SleepIndefinitely)
        sleepingThread.Name = "Sleeping2"
        sleepingThread.Start()
        Thread.Sleep(2000)
        sleepingThread.Abort()
    End Sub

    Private Sub SleepIndefinitely()
        Console.WriteLine("Thread '{0}' about to sleep indefinitely.",
                          Thread.CurrentThread.Name)
        Try
            Thread.Sleep(Timeout.Infinite)
        Catch ex As ThreadInterruptedException
            Console.WriteLine("Thread '{0}' awoken.",
                              Thread.CurrentThread.Name)
        Catch ex As ThreadAbortException
            Console.WriteLine("Thread '{0}' aborted.",
                              Thread.CurrentThread.Name)
        Finally
            Console.WriteLine("Thread '{0}' executing finally block.",
                              Thread.CurrentThread.Name)
        End Try
        Console.WriteLine("Thread '{0}' finishing normal execution.",
                          Thread.CurrentThread.Name)
        Console.WriteLine()
    End Sub
End Module
' The example displays the following output:
'       Thread 'Sleeping' about to sleep indefinitely.
'       Thread 'Sleeping' awoken.
'       Thread 'Sleeping' executing finally block.
'       Thread 'Sleeping finishing normal execution.
'       
'       Thread 'Sleeping2' about to sleep indefinitely.
'       Thread 'Sleeping2' aborted.
'       Thread 'Sleeping2' executing finally block.

Interruzione dei thread

È possibile interrompere un thread in attesa chiamando il metodo Thread.Interrupt sul thread bloccato per generare un oggetto ThreadInterruptedException, che consente al thread di uscire dalla chiamata di blocco. Il thread deve intercettare ThreadInterruptedException e eseguire qualsiasi operazione appropriata per continuare a funzionare. Se il thread ignora l'eccezione, il runtime intercetta l'eccezione e arresta il thread.

Nota

Se il thread di destinazione non viene bloccato quando Thread.Interrupt viene chiamato, il thread non viene interrotto fino a quando non si blocca. Se il thread non si blocca mai, potrebbe essere completato senza mai essere interrotto.

Se un'attesa è un'attesa gestita, allora sia Thread.Interrupt che Thread.Abort riattivano immediatamente il thread. Se un'attesa è un'attesa non gestita (ad esempio, una chiamata platform invoke alla funzione Win32 WaitForSingleObject ), né Thread.InterruptThread.Abort possono assumere il controllo del thread fino a quando non ritorna o non chiama nel codice gestito. Nel codice gestito il comportamento è il seguente:

Vedere anche