Manufaturação industrial
Internet das coisas industrial | Materiais industriais | Manutenção e reparo de equipamentos | Programação industrial |
home  MfgRobots >> Manufaturação industrial >  >> Industrial programming >> Linguagem C

Dominando Multithreading em C#: Aumente Performance e Eficiência

Um thread é definido como o caminho de execução de um programa. Cada thread define um fluxo de controle único. Se sua aplicação envolve operações complicadas e demoradas, muitas vezes é útil definir diferentes caminhos de execução ou threads, com cada thread executando um trabalho específico.

Threads são processos leves. Um exemplo comum de uso de thread é a implementação de programação concorrente por sistemas operacionais modernos. O uso de threads economiza ciclos de CPU e aumenta a eficiência de uma aplicação.

Até agora escrevemos programas onde uma única thread roda como um único processo, que é a instância em execução da aplicação. No entanto, dessa forma a aplicação pode executar um trabalho por vez. Para fazê-la executar mais de uma tarefa ao mesmo tempo, ela pode ser dividida em threads menores.

Ciclo de Vida da Thread

O ciclo de vida de uma thread começa quando um objeto da classe System.Threading.Thread é criado e termina quando a thread é terminada ou completa a execução.

Seguem os vários estados no ciclo de vida de uma thread:

A Thread Principal

Em C#, a classe System.Threading.Thread é usada para trabalhar com threads. Ela permite criar e acessar threads individuais em uma aplicação multithread. A primeira thread a ser executada em um processo é chamada de thread principal (main thread).

Quando um programa C# inicia a execução, a thread principal é criada automaticamente. As threads criadas usando a classe Thread são chamadas de threads filhas da thread principal. Você pode acessar uma thread usando a propriedade CurrentThread da classe Thread.

O programa a seguir demonstra execução da thread principal:

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

Quando o código acima é compilado e executado, produz o seguinte resultado:

Esta é MainThread

Propriedades e Métodos da Classe Thread

A tabela a seguir mostra algumas das propriedades mais comumente usadas da classe Thread:

Nº Propriedade e Descrição
1

CurrentContext

Obtém o contexto atual no qual a thread está executando.

2

CurrentCulture

Obtém ou define a cultura para a thread atual.

3

CurrentPrinciple

Obtém ou define o principal atual da thread (para segurança baseada em função).

4

CurrentThread

Obtém a thread em execução no momento.

5

CurrentUICulture

Obtém ou define a cultura atual usada pelo Resource Manager para procurar recursos específicos de cultura em tempo de execução.

6

ExecutionContext

Obtém um objeto ExecutionContext que contém informações sobre os vários contextos da thread atual.

7

IsAlive

Obtém um valor indicando o status de execução da thread atual.

8

IsBackground

Obtém ou define um valor indicando se uma thread é uma thread de background.

9

IsThreadPoolThread

Obtém um valor indicando se uma thread pertence ao pool de threads gerenciado.

10

ManagedThreadId

Obtém um identificador único para a thread gerenciada atual.

11

Name

Obtém ou define o nome da thread.

12

Priority

Obtém ou define um valor indicando a prioridade de agendamento de uma thread.

13

ThreadState

Obtém um valor contendo os estados da thread atual.

A tabela a seguir mostra alguns dos métodos mais comumente usados da classe Thread:

Nº Método e Descrição
1

public void Abort()

Lança uma ThreadAbortException na thread em que é invocada, para iniciar o processo de término da thread. Chamar este método geralmente termina a thread.

2

public static LocalDataStoreSlot AllocateDataSlot()

Aloca um slot de dados sem nome em todas as threads. Para melhor performance, use campos marcados com o atributo ThreadStaticAttribute.

3

public static LocalDataStoreSlot AllocateNamedDataSlot(string name)

Aloca um slot de dados nomeado em todas as threads. Para melhor performance, use campos marcados com o atributo ThreadStaticAttribute.

4

public static void BeginCriticalRegion()

Notifica um host que a execução está prestes a entrar em uma região de código onde os efeitos de um abort de thread ou exceção não tratada podem comprometer outras tarefas no domínio da aplicação.

5

public static void BeginThreadAffinity()

Notifica um host que código gerenciado está prestes a executar instruções que dependem da identidade da thread física do sistema operacional atual.

6

public static void EndCriticalRegion()

Notifica um host que a execução está prestes a entrar em uma região de código onde os efeitos de um abort de thread ou exceção não tratada são limitados à tarefa atual.

7

public static void EndThreadAffinity()

Notifica um host que código gerenciado terminou de executar instruções que dependem da identidade da thread física do sistema operacional atual.

8

public static void FreeNamedDataSlot(string name)

Elimina a associação entre um nome e um slot, para todas as threads no processo. Para melhor performance, use campos marcados com o atributo ThreadStaticAttribute.

9

public static Object GetData(LocalDataStoreSlot slot)

Recupera o valor do slot especificado na thread atual, dentro do domínio atual da thread. Para melhor performance, use campos marcados com o atributo ThreadStaticAttribute.

10

public static AppDomain GetDomain()

Retorna o domínio atual no qual a thread atual está rodando.

11

public static AppDomain GetDomainID()

Retorna um identificador único de domínio de aplicação.

12

public static LocalDataStoreSlot GetNamedDataSlot(string name)

Procura um slot de dados nomeado. Para melhor performance, use campos marcados com o atributo ThreadStaticAttribute.

13

public void Interrupt()

Interrompe uma thread que está no estado WaitSleepJoin.

14

public void Join()

Bloqueia a thread chamadora até que uma thread termine, enquanto continua a realizar pumping padrão de COM e SendMessage. Este método tem diferentes formas sobrecarregadas.

15

public static void MemoryBarrier()

Sincroniza acesso à memória: O processador executando a thread atual não pode reordenar instruções de forma que acessos à memória antes da chamada a MemoryBarrier executem após acessos que seguem a chamada.

16

public static void ResetAbort()

Cancela um Abort solicitado para a thread atual.

17

public static void SetData(LocalDataStoreSlot slot, Object data)

Define os dados no slot especificado na thread em execução no momento, para o domínio atual da thread. Para melhor performance, use campos marcados com o atributo ThreadStaticAttribute.

18

public void Start()

Inicia uma thread.

19

public static void Sleep(int millisecondsTimeout)

Faz a thread pausar por um período de tempo.

20

public static void SpinWait(int iterations)

Faz uma thread aguardar o número de vezes definido pelo parâmetro iterations.

21

public 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 de um campo. O valor é o mais recente escrito por qualquer processador em um computador, independentemente do número de processadores ou estado do cache do processador. Este método tem diferentes formas sobrecarregadas. Apenas algumas são dadas acima.

22

public 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 um valor em um campo imediatamente, para que o valor seja visível para todos os processadores no computador. Este método tem diferentes formas sobrecarregadas. Apenas algumas são dadas acima.

23

public static bool Yield()

Faz a thread chamadora ceder execução para outra thread que está pronta para rodar no processador atual. O sistema operacional seleciona a thread para ceder.

Criando Threads

Threads são criadas estendendo a classe Thread. A classe Thread estendida então chama o método Start() para iniciar a execução da thread filha.

O programa a seguir demonstra o conceito:

Demo ao Vivo
using System; 
using System.Threading; 
namespace MultithreadingApplication { 
    class ThreadCreationProgram { 
        public static void CallToChildThread() { 
            Console.WriteLine("Thread filha inicia"); 
        } 
        static void Main(string[] args) { 
            ThreadStart childref = new ThreadStart(CallToChildThread); 
            Console.WriteLine("No Main: Criando a thread filha"); 
            Thread childThread = new Thread(childref); 
            childThread.Start(); 
            Console.ReadKey(); 
        } 
    } 
}

Quando o código acima é compilado e executado, produz o seguinte resultado:

No Main: Criando a thread filha 
Thread filha inicia

Gerenciando Threads

A classe Thread fornece vários métodos para gerenciar threads.

O exemplo a seguir demonstra o uso do método Sleep() para fazer uma thread pausar por um período específico de tempo.

Demo ao Vivo
using System; 
using System.Threading; 
namespace MultithreadingApplication { 
    class ThreadCreationProgram { 
        public static void CallToChildThread() { 
            Console.WriteLine("Thread filha inicia"); 
            // a thread é pausada por 5000 milissegundos 
            int sleepfor = 5000; 
            Console.WriteLine("Thread Filha Pausada por {0} segundos", sleepfor / 1000); 
            Thread.Sleep(sleepfor); 
            Console.WriteLine("Thread filha retoma"); 
        } 
        static void Main(string[] args) { 
            ThreadStart childref = new ThreadStart(CallToChildThread); 
            Console.WriteLine("No Main: Criando a thread filha"); 
            Thread childThread = new Thread(childref); 
            childThread.Start(); 
            Console.ReadKey(); 
        } 
    } 
}

Quando o código acima é compilado e executado, produz o seguinte resultado:

No Main: Criando a thread filha 
Thread filha inicia 
Thread Filha Pausada por 5 segundos 
Thread filha retoma

Destruindo Threads

O método Abort() é usado para destruir threads.

O runtime aborta a thread lançando uma ThreadAbortException. Esta exceção não pode ser capturada, o controle é enviado para o bloco finally, se houver.

O programa a seguir ilustra isso:

Demo ao Vivo
using System; 
using System.Threading; 
namespace MultithreadingApplication { 
    class ThreadCreationProgram { 
        public static void CallToChildThread() { 
            try { 
                Console.WriteLine("Thread filha inicia"); 
                // faz algum trabalho, como contar até 10 
                for (int counter = 0; counter <= 10; counter++) { 
                    Thread.Sleep(500); 
                    Console.WriteLine(counter); 
                } 
                Console.WriteLine("Thread Filha Concluída"); 
            } catch (ThreadAbortException e) { 
                Console.WriteLine("Exceção Thread Abort"); 
            } finally { 
                Console.WriteLine("Não foi possível capturar a Thread Exception"); 
            } 
        } 
        static void Main(string[] args) { 
            ThreadStart childref = new ThreadStart(CallToChildThread); 
            Console.WriteLine("No Main: Criando a thread filha"); 
            Thread childThread = new Thread(childref); 
            childThread.Start(); 
            //para a thread principal por algum tempo 
            Thread.Sleep(2000); 
            //agora aborta a filha 
            Console.WriteLine("No Main: Abortando a thread filha"); 
            childThread.Abort(); 
            Console.ReadKey(); 
        } 
    } 
}

Quando o código acima é compilado e executado, produz o seguinte resultado:

No Main: Criando a thread filha 
Thread filha inicia 
0 
1 
2 
No Main: Abortando a thread filha 
Thread Abort Exception 
Couldn't catch the Thread Exception

Linguagem C

  1. Diâmetros Menor vs Maior da Rosca: Como Escolher o Tamanho Certo do Parafuso
  2. Linha: Tipos, História, Produção e Controle de Qualidade
  3. Thread vs. ZigBee: Comparação Técnica para Engenheiros de IoT
  4. Escolhendo o Tratamento de Rosca Adequado: Aumentando Confiabilidade e Reduzindo Paradas
  5. Domine o Multithreading em C++: Programação Concorrente Eficiente com Pthreads
  6. Programação Multithread em Python: Concorrência Eficiente
  7. Computação de Borda Ganha Estrutura Clara Aprovada pela Indústria
  8. Iluminação Traseira Rápida: Capturando Mais de 1 Milhão de FPS
  9. Desvendando o Fio Digital: Blueprint da Siemens PLM para Manufatura Inteligente
  10. Entendendo Cortadores de Rosca (Thread Cutters): Tipos, Usos e Aplicações