English | 简体中文 | 繁體中文 | Русский язык | Français | Español | Português | Deutsch | 日本語 | 한국어 | Italiano | بالعربية

Multithreading do C#

Thread definida como o caminho de execução do programa. Cada thread define um fluxo de controle único. Se o seu aplicativo envolver operações complexas e demoradas, configurar diferentes caminhos de execução de threads geralmente é benéfico, com cada thread executando um trabalho específico.

Thread éProcesso leveUm exemplo comum de uso de threads é a implementação de programação paralela em sistemas operacionais modernos. O uso de threads economiza o desperdício de ciclos de CPU, aumentando a eficiência do aplicativo.

Até agora, o programa que escrevemos é um exemplo de processo单一的 execução da aplicação de thread única como exemplo de execução da aplicação. No entanto, dessa forma, a aplicação pode executar apenas uma tarefa ao mesmo tempo. Para executar várias tarefas ao mesmo tempo, ela pode ser dividida em threads menores.

Vida do thread

A vida do thread começa quando o objeto da classe System.Threading.Thread é criado, termina quando o thread é terminado ou concluído.

A seguir, estão listados os vários estados da vida do thread:

  • Estado não iniciado: estado quando o exemplo do thread é criado, mas o método Start não foi chamado.

  • Estado pronto: estado quando o thread está pronto para executar e está esperando um ciclo de CPU.

  • Estado não executável: nas seguintes situações, o thread não pode ser executado:

    • já foi chamado o método Sleep

    • já foi chamado o método Wait

    • através de I/O operação está bloqueada

  • Estado morto: estado quando o thread termina a execução ou é interrompido.

Thread principal

No C#,System.Threading.Thread A classe é usada para o trabalho de thread. Ela permite criar e acessar um único thread em aplicações multithread.Thread principal.

Quando o programa C# começa a ser executado, o thread principal é criado automaticamente. Use Thread A classe criada chama o thread do sub-thread da thread principal. Você pode usar a classe Thread CurrentThread Acesso a propriedades do thread.

O seguinte programa demonstra a execução do thread principal:

using System;
using System.Threading;
namespace MultithreadingApplication
{
    class MainThreadProgram
    {
        static void Main(string[] args)
        {
            Thread th = Thread.CurrentThread;
            th.Name = "MainThread";
            Console.WriteLine("This is {0}", th.Name);
            Console.ReadKey();
        }
    }
}

Quando o código acima for compilado e executado, ele produzirá o seguinte resultado:

This is MainThread

Propriedades e métodos comuns da classe Thread

A tabela a seguir lista Thread Alguns métodos comuns de uma classe Propriedades:

PropriedadesDescrição
CurrentContextObtém o contexto atual onde a thread está executando.
CurrentCultureObtém ou define a regionalidade atual da thread.
CurrentPrincipalObtém ou define o responsável atual da thread (para segurança baseada em papel).
CurrentThreadObtém a thread que está em execução atualmente.
CurrentUICultureObtém ou define a regionalidade atual usada pelo gerenciador de recursos para encontrar recursos específicos da regionalidade durante a execução.
ExecutionContextObtém um objeto ExecutionContext que contém informações sobre vários contextos da thread atual.
IsAliveObter um valor que indica o estado de execução da thread atual.
IsBackgroundObter ou definir um valor que indica se uma thread é uma thread de fundo.
IsThreadPoolThreadObter um valor que indica se a thread pertence ao pool de threads gerenciadas.
ManagedThreadIdObter o identificador exclusivo da thread gerenciada.
NameObter ou definir o nome da thread.
PriorityObter ou definir um valor que indica a prioridade de escalonamento da thread.
ThreadStateObter um valor que contém o estado atual da thread.

A tabela a seguir lista Thread Alguns métodos comuns de uma classe Método:

NúmeroNome do método & Descrição
1public void Abort()
Gerar ThreadAbortException na thread que chama este método para iniciar o processo de encerramento deste thread. A chamada deste método geralmente terminará a thread.
2public static LocalDataStoreSlot AllocateDataSlot()
Atribuir slots de dados não nomeados em todas as threads. Para obter melhor desempenho, use campos marcados com a propriedade ThreadStaticAttribute.
3public static LocalDataStoreSlot AllocateNamedDataSlot( string name)
Atribuir slots de dados nomeados em todas as threads. Para obter melhor desempenho, use campos marcados com a propriedade ThreadStaticAttribute.
4public static void BeginCriticalRegion()
Notificar o anfitrião de que ele está prestes a entrar em uma área de código, onde a interrupção da thread ou a exceção não tratada pode prejudicar outras tarefas no domínio do aplicativo.
5public static void BeginThreadAffinity()
Notificar o anfitrião do código hospedado que ele está prestes a executar uma instrução dependente do identificador da thread do sistema operacional físico.
6public static void EndCriticalRegion()
Notificar o anfitrião de que ele está prestes a entrar em uma área de código, onde a interrupção da thread ou a exceção não tratada afetará apenas a tarefa atual.
7public static void EndThreadAffinity()
Notificar o anfitrião do código hospedado que a instrução dependente do identificador da thread do sistema operacional físico foi executada.
8public static void FreeNamedDataSlot(string name)
为进程中的所有线程消除名称与槽之间的关联。为了获得更好的性能,请改用以 ThreadStaticAttribute 属性标记的字段。
9public static Object GetData( LocalDataStoreSlot slot )
在当前线程的当前域中从当前线程上指定的槽中检索值。为了获得更好的性能,请改用以 ThreadStaticAttribute 属性标记的字段。
10public static AppDomain GetDomain()
返回当前线程正在其中运行的当前域。
11public static AppDomain GetDomainID()
返回唯一的应用程序域标识符。
12public static LocalDataStoreSlot GetNamedDataSlot( string name )
查找已命名的数据槽。为了获得更好的性能,请改用以 ThreadStaticAttribute 属性标记的字段。
13public void Interrupt()
中断处于 WaitSleepJoin 线程状态的线程。
14public void Join()
在继续执行标准的 COM 和 SendMessage 消息泵处理期间,阻塞调用线程,直到某个线程终止为止。此方法有不同的重载形式。
15public static void MemoryBarrier()
按如下方式同步内存存取:执行当前线程的处理器在对指令重新排序时,不能采用先执行 MemoryBarrier 调用之后的内存存取,再执行 MemoryBarrier 调用之前的内存存取的方式。
16public static void ResetAbort()
取消为当前线程请求的 Abort。
17public static void SetData( LocalDataStoreSlot slot, Object data )
在当前正在运行的线程上为此线程的当前域在指定槽中设置数据。为了获得更好的性能,请改用以 ThreadStaticAttribute 属性标记的字段。
18public void Start()
开始一个线程。
19public static void Sleep( int millisecondsTimeout )
faz a thread pausar por um tempo.
20public static void SpinWait( int iterations )
causa a thread a esperar o tempo definido pelo parâmetro iterations.
21public static byte VolatileRead( ref byte address )
public static double VolatileRead( ref double address )
public static int VolatileRead( ref int address )
public static Object VolatileRead( ref Object address )

Lê o valor do campo. independentemente do número de processadores ou do estado do cache do processador, o valor é o mais recente escrito por qualquer processador do computador. Este método tem várias sobreposições. Aqui estão algumas delas.
22public static void VolatileWrite( ref byte address, byte value )
public static void VolatileWrite( ref double address, double value )
public static void VolatileWrite( ref int address, int value )
public static void VolatileWrite( ref Object address, Object value )

Escreve imediatamente um valor no campo, tornando-o visível para todos os processadores no computador. Este método tem várias sobreposições. Aqui estão algumas delas.
23public static bool Yield();
causa a chamada da thread para preparar a execução de outra thread pronta para rodar no processador atual. A escolha da thread a ser executada é feita pelo sistema operacional.

criação de threads

As threads são criadas através da extensão da classe Thread. A extensão da classe Thread chama Start(); métodos para iniciar a execução da thread subsequente.

O programa a seguir demonstra este conceito:

using System;
using System.Threading;
namespace MultithreadingApplication
{
    class ThreadCreationProgram
    {
        public static void CallToChildThread()
        {
            Console.WriteLine("Child thread starts");
        }
        
        static void Main(string[] args)
        {
            ThreadStart childref = new ThreadStart(CallToChildThread);
            Console.WriteLine("In Main: Creating the Child thread");
            Thread childThread = new Thread(childref);
            childThread.Start();
            Console.ReadKey();
        }
    }
}

Quando o código acima for compilado e executado, ele produzirá o seguinte resultado:

Em Main: Criando a Thread Filha
Thread Filha Inicia

gerenciamento de threads

A classe Thread oferece várias métodos para gerenciar threads.

O exemplo a seguir ilustra sleep(); uso do método, destinado a pausar a thread por um tempo específico.

using System;
using System.Threading;
namespace MultithreadingApplication
{
    class ThreadCreationProgram
    {
        public static void CallToChildThread()
        {
            Console.WriteLine("Child thread starts");
            // pausa da thread 5000 milissegundos
            int sleepfor = 5000; 
            Console.WriteLine("Thread filha pausada por {0} segundos", 
                              sleepfor / 1000);
            Thread.Sleep(sleepfor);
            Console.WriteLine("Filho da thread continua");
        }
        
        static void Main(string[] args)
        {
            ThreadStart childref = new ThreadStart(CallToChildThread);
            Console.WriteLine("In Main: Creating the Child thread");
            Thread childThread = new Thread(childref);
            childThread.Start();
            Console.ReadKey();
        }
    }
}

Quando o código acima for compilado e executado, ele produzirá o seguinte resultado:

Em Main: Criando a Thread Filha
Thread Filha Inicia
Thread filha pausada por 5 segundos
A thread filha continua

destruir a thread

Abort() método é usado para destruir a thread.

através de lançamento threadabortexception interromper a thread em tempo de execução. Essa exceção não pode ser capturada, se houver finally bloco, o controle será enviado para finally bloco.

O seguinte programa ilustra isso:

using System;
using System.Threading;
namespace MultithreadingApplication
{
    class ThreadCreationProgram
    {
        public static void CallToChildThread()
        {
            try
            {
                Console.WriteLine("Child thread starts");
                // contar até 10
                for(int counter = 0; counter <= 10; counter++)
                {
                    Thread.Sleep(500);
                    Console.WriteLine(counter);
                }
                Console.WriteLine("Child Thread Completed");
            }
            catch(ThreadAbortException e)
            {
                Console.WriteLine("Thread Abort Exception");
            }
            finally
            {
                Console.WriteLine("Couldn't catch the Thread Exception");
            }
        }
        
        static void Main(string[] args)
        {
            ThreadStart childref = new ThreadStart(CallToChildThread);
            Console.WriteLine("In Main: Creating the Child thread");
            Thread childThread = new Thread(childref);
            childThread.Start();
            // Parar a thread principal por um tempo
            Thread.Sleep(2000);
            // Agora está interrompendo a thread filha
            Console.WriteLine("In Main: Aborting the Child thread");
            childThread.Abort();
            Console.ReadKey();
        }
    }
}

Quando o código acima for compilado e executado, ele produzirá o seguinte resultado:

Em Main: Criando a Thread Filha
Thread Filha Inicia
0
1
2
Em Main: Abortando a Thread Filha
Exceção de Abortamento da Thread
Não foi possível capturar a Exceção da Thread