Partilhar via


Pausar e interromper threads

As formas mais comuns de sincronizar as atividades das threads são bloquear e libertar threads, ou bloquear objetos ou regiões de código. Para obter mais informações sobre estes mecanismos de bloqueio e bloqueio, consulte Visão Geral das Primitivas de Sincronização.

Também podes fazer com que os fios se adormecam sozinhos. Quando as threads estão bloqueadas ou em suspensão, pode usar um ThreadInterruptedException para retirá-las do seu estado de espera.

O método Thread.Sleep

Chamar o método Thread.Sleep faz com que a linha de execução atual bloqueie imediatamente pelo número de milissegundos ou pelo intervalo de tempo que é passado ao método, e dá o restante da sua fatia de tempo a outra linha de execução. Quando esse intervalo termina, o fio de dormência retoma a execução.

Uma thread não pode chamar Thread.Sleep em outra thread. Thread.Sleep é um método estático que faz sempre com que a thread corrente entre em suspensão.

Chamar Thread.Sleep com um valor de Timeout.Infinite faz com que uma thread durma até que outra thread chame o método Thread.Interrupt na thread que está a dormir. O exemplo seguinte ilustra a interrupção de um fio de suspensão.

using System;
using System.Threading;

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

    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.");
        }
        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.
Imports System.Threading

Module Example
    Public Sub Main()
        ' Interrupt a sleeping thread.
        Dim sleepingThread = New Thread(AddressOf SleepIndefinitely)
        sleepingThread.Name = "Sleeping"
        sleepingThread.Start()
        Thread.Sleep(2000)
        sleepingThread.Interrupt()
        sleepingThread.Join()
    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)
        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.

O exemplo chama Thread.Join para bloquear o subprocesso chamador até que o subprocesso interrompido termine a execução.

Interrupção de threads

Pode interromper uma thread em espera chamando o método Thread.Interrupt na thread bloqueada para lançar um ThreadInterruptedException, que remove a thread da chamada de bloqueio. A linha deve apanhar o ThreadInterruptedException e fazer o que for necessário para continuar a trabalhar. Se a thread ignorar a exceção, o tempo de execução apanha a exceção e pára a thread.

Observação

Se o thread de destino não estiver bloqueado quando Thread.Interrupt for chamado, o thread não será interrompido até ser bloqueado. Se a linha de execução nunca bloquear, pode concluir-se sem nunca ser interrompida.

Se a espera for uma espera gerida, Thread.Interrupt ativa o thread imediatamente. Se uma espera for uma espera não gerida (por exemplo, uma chamada de plataforma para a função WaitForSingleObject do Win32), Thread.Interrupt não pode assumir controlo sobre o thread até que ele retorne ou faça uma chamada para código gerido. No código gerido, o comportamento é o seguinte:

Consulte também