Um thread é definido como o caminho de execução de um programa. Cada thread define um controle de fluxo exclusivo. Se o seu aplicativo envolve operações complexas e demoradas, como acesso ao banco de dados ou algumas operações intensas de E/S, geralmente é muito benéfico configurar diferentes caminhos de execução ou threads, cada thread executando uma tarefa específica.
Threads são processos leves. Um exemplo comum do uso de threads é a implementação de programação paralela em sistemas operacionais modernos. O uso de threads evita a perda de ciclos de CPU e melhora a eficiência do aplicativo.
O programa que compilamos até agora é executado como um único processo em um thread, que é a instância em execução do aplicativo. No entanto, tal aplicação só pode executar uma tarefa por vez. Para que ele execute várias tarefas ao mesmo tempo, você pode dividi-lo em threads menores.
No .Net, os threads são tratados por meio do namespace 'System.Threading'. Criar uma variável do tipo system.threading.thread permite criar um novo thread e começar a trabalhar nele. Ele permite criar e acessar threads independentes em um thread separado.
Um thread é criado a partir de um objeto thread e seu construtor recebe uma referência para iniciar o thread.
ThreadStart ameaçafilha = new ThreadStart(childthreadcall);
O ciclo de vida de um thread começa quando um objeto da classe system.threading.thread é criado e termina quando o thread é encerrado ou a execução é concluída.
A seguir estão os vários estados do ciclo de vida de um thread:
Estado de início pendente: a instância do thread foi criada, mas o método de inicialização não foi chamado.
Estado pronto: uma situação em que um thread está pronto para ser executado e aguardando um ciclo de CPU.
Estado não executável: quando um thread não pode ser executado, existem várias possibilidades:
O método sleep atual é chamado
O método de espera é chamado
Bloqueado pela operação de E/S
Estado de morte: o thread concluiu a execução ou foi encerrado.
O atributo de prioridade na classe Thread especifica principalmente a prioridade de um thread em relação a outros threads. O tempo de execução do .NET seleciona o thread pronto com a prioridade mais alta. A prioridade pode ser dividida em:
mais alto que o normal
abaixo do normal
Mais alto
mais baixo
normal
Depois que um thread é criado, o sistema define sua prioridade usando o sistema de configuração de prioridade da classe Thread.
NewThread.Priority = ThreadPriority.Highest;
A classe thread possui os seguintes recursos importantes:
propriedade | descrever |
---|---|
Contexto Atual | Obtenha o conteúdo do thread atualmente em execução. |
Cultura Atual | Obtém ou define o ambiente do thread atual. |
Princípio Atual | Obtém ou define a política de segurança baseada em função do processo atual. |
Tópico Atual | Obtenha o thread atualmente em execução. |
Cultura UI atual | Obtém ou define o ambiente atual usado pelo gerenciador de recursos do processo em execução para localizar recursos específicos. |
Contexto de Execução | Obtém um objeto ExecutionContext que contém informações contextuais sobre o thread atual. |
Está Vivo | Obtém um valor que indica o status de execução do thread atual. |
ÉFundo | Background Obtém ou define um valor que indica se o thread é um thread em segundo plano. |
IsThreadPoolThread | Obtém um valor que indica se o thread pertence ao pool de threads gerenciado. |
ID de thread gerenciado | Obtém o identificador exclusivo atual do thread gerenciado. |
Nome | Obtém ou define o nome do thread. |
Prioridade | Obtém ou define um valor que indica a prioridade de agendamento de um thread. |
ThreadState | Obtém um valor que contém o status do thread atual. |
A classe thread possui os seguintes métodos importantes:
método | descrever |
---|---|
Abortar | Chamar um ThreadAbortException inicia o processo de encerramento do thread. Chamar esse método geralmente encerra o thread. |
AlocarDataSlot | Todos os threads recebem um slot de dados sem nome. Para melhor desempenho, use campos marcados com o atributo ThreadStaticAttribute. |
AlocarNamedDataSlot | Aloque slots de dados nomeados para todos os threads. Para melhor desempenho, use campos marcados com o atributo ThreadStaticAttribute. |
BeginCriticalRegion | Notifica o host de que a execução está prestes a entrar em uma região de código onde os efeitos de uma interrupção de thread ou de uma exceção não tratada podem comprometer outras tarefas. |
BeginThreadAffinity | Notifica o host de que o código gerenciado está prestes a ser executado, dependendo da identidade do thread do sistema operacional físico atual. |
EndCriticalRegion | Notifica o host de que a execução está prestes a entrar em uma região de código onde uma interrupção de thread ou uma exceção não tratada afeta apenas a tarefa atual. |
EndThreadAffinity | Notifica o host de que a execução do código gerenciado foi concluída, dependendo da identidade do thread do sistema operacional físico atual. |
FreeNamedDataSlot | Elimina a associação entre nomes e slots para todos os threads do processo. Para melhor desempenho, utilize campos marcados com o atributo ThreadStaticAttribute. |
Obter dados | Recupera o valor do slot especificado pelo thread atual no domínio atual do thread atual. Para melhor desempenho, use campos marcados com o atributo ThreadStaticAttribute. |
ObterDomínio | Retorna o thread atualmente em execução no domínio atual. |
ObterIDDomínio | Retorna o identificador exclusivo do domínio do aplicativo. |
GetNamedDataSlot | Encontre um slot de dados nomeado. Para melhor desempenho, use campos marcados com o atributo ThreadStaticAttribute. |
Interromper | Interromper um thread no estado de thread WaitSleepJoin. |
Juntar | Bloqueia o thread de chamada até que um dos threads termine, enquanto continua a execução COM e SendMessage padrão. Este método possui diferentes formas sobrecarregadas. |
Barreira de Memória | Os acessos síncronos à memória são os seguintes: o acelerador que processa o thread atual não pode reordenar as instruções de forma que o acesso à memória chame MemoryBarrier seguido pela execução do acesso à memória. |
RedefinirAbortar | Cancela a solicitação de anulação do thread atual. |
Definir dados | Define os dados do thread em execução atual no intervalo de tempo especificado e o domínio atual desse thread. Para melhor desempenho, o domínio do aplicativo possui o atributo ThreadStaticAttribute do domínio. |
Começar | Inicie um tópico. |
Dormir | Faz com que o thread seja pausado por um período de tempo. |
Girar, esperar | Faz a thread aguardar o número de iterações definido pelo parâmetro. |
Leitura volátil() | Leia o valor do campo. O valor mais recente é gravado por qualquer processador do computador, independentemente do processador ou do número do estado do cache do processador. Este método possui diferentes formas sobrecarregadas. |
VolátilWrite() | Grava imediatamente um valor em um campo que fica visível para todos os processadores do computador. Este método possui diferentes formas sobrecarregadas. |
Colheita | Faz com que o thread de chamada execute outro thread que pode ser executado no processador atual e o sistema operacional escolhe redirecionar o thread |
O exemplo a seguir ilustra o uso de classes de thread. A página possui um rótulo de controle que exibe mensagens de threads filhos. As mensagens do programa principal são exibidas diretamente usando o método response.write(50), portanto aparecem no topo da página.
Os arquivos de origem são os seguintes:
<%@ Page Language="C#" AutoEventWireup="true" CodeBehind="Default.aspx.cs" Inherits="threaddemo._Default" %> <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional// PT" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd"> <html xmlns="http://www.w3.org/1999/xhtml" > <head runat="server"> <title> Página sem título </title> </head> <body> <form id="form1 " runat="server"> <div> <h3>Exemplo de thread</h3> </div> <asp:Label ID="lblmessage" runat="server" Text="Label"> </asp:Label> < /formulário> </body> </html>
O código de fundo é o seguinte:
usando System.Collections; usando System.Web.UI; usando System.Web.HtmlControls; ; usando System.Web.UI.WebControls; usando System.Web.UI.WebControls.WebParts usando System.Xml.Linq; usando System.Threading; class _Default: System.Web.UI.Page { protected void Page_Load(objeto remetente, EventArgs e) { ThreadStart childthreat = new ThreadStart(childthreadcall("Thread filho iniciado <br/>"); Thread(childthreat); child.Start(); Response.Write("Principal dormindo por 2 segundos....<br/>"); Thread.Sleep(2000); Response.Write("<br/>Thread filho principal anulado<br/>"); child.Abort() } public void childthreadcall() { try{ lblmessage.Text = "<br/ >Tópico filho iniciado <br/>"; lblmessage.Text += "Tópico filho: Contando até 10"; for( int i =0; i<10; i++) { Thread.Sleep(500); lblmessage.Text += "<br/> no thread filho </br>"; catch(ThreadAbortException e){ lblmessage.Text += "<br /> thread filho - exceção" }finalmente{ lblmessage.Text += "<br /> thread filho - não foi possível capturar a exceção";
Quando a página é carregada, um novo thread é iniciado com childthreadcall() como referência. As atividades do tópico principal serão exibidas diretamente na página web.
Um segundo thread é executado e envia a mensagem para a tag de controle.
O thread principal fica suspenso por 2.000 milissegundos enquanto o thread filho está em execução.
O thread filho continua em execução até ser encerrado pelo thread principal e, em seguida, lança uma ThreadAbortException e é encerrado.
O controle retorna ao thread principal.
Ao ser executado o programa enviará as seguintes informações: