Observação
O acesso a essa página exige autorização. Você pode tentar entrar ou alterar diretórios.
O acesso a essa página exige autorização. Você pode tentar alterar os diretórios.
Aplicativos que executam muitas tarefas simultaneamente, mas permanecem responsivos à interação do usuário, geralmente exigem um design que usa vários threads. O System.Threading namespace fornece todas as ferramentas necessárias para criar aplicativos multithreaded de alto desempenho, mas usar essas ferramentas efetivamente requer uma experiência significativa com engenharia de software multithread. Para aplicativos com multi-thread relativamente simples, o componente BackgroundWorker oferece uma solução direta. Para aplicativos assíncronos mais sofisticados, considere implementar uma classe que adere ao padrão assíncrono baseado em evento.
O Padrão Assíncrono baseado em eventos oferece as vantagens dos aplicativos multiencadeados e oculta muitos dos problemas complexos inerentes ao design multiencadeado. O uso de uma classe que dá suporte a esse padrão pode permitir que você:
Execute tarefas demoradas, como downloads e operações de banco de dados, "em segundo plano", sem interromper seu aplicativo.
Execute várias operações simultaneamente, recebendo notificações quando cada uma for concluída.
Aguarde até que os recursos fiquem disponíveis sem parar ("bloquear") seu aplicativo.
Comunicar-se com operações assíncronas pendentes usando o modelo familiar de eventos e representantes. Para obter mais informações sobre como usar manipuladores de eventos e delegados, consulte Eventos.
Uma classe que dá suporte ao Padrão Assíncrono baseado em evento terá um ou mais métodos chamados MethodNameAsync. Esses métodos podem espelhar versões síncronas, que executam a mesma operação no thread atual. A classe também pode ter um evento MethodNameCompleted e pode ter um método MethodNameAsyncCancel (ou simplesmente CancelAsync).
PictureBox é um componente típico que dá suporte ao padrão assíncrono baseado em evento. Você pode baixar uma imagem de forma síncrona chamando seu Load método, mas se a imagem for grande ou se a conexão de rede estiver lenta, seu aplicativo deixará de responder até que a operação de download seja concluída e a chamada seja Load retornada.
Se você quiser que seu aplicativo continue em execução enquanto a imagem estiver carregando, você pode chamar o LoadAsync método e manipular o LoadCompleted evento, assim como você manipularia qualquer outro evento. Quando você chamar o LoadAsync método, seu aplicativo continuará a ser executado enquanto o download continua em um thread separado ("em segundo plano"). Seu manipulador de eventos será chamado quando a operação de carregamento de imagem for concluída e seu manipulador de eventos poderá examinar o AsyncCompletedEventArgs parâmetro para determinar se o download foi concluído com êxito.
O padrão assíncrono baseado em evento requer que uma operação assíncrona possa ser cancelada, e o PictureBox controle suporta esse requisito com seu CancelAsync método. A chamada CancelAsync envia uma solicitação para interromper o download pendente e, quando a tarefa é cancelada, o evento LoadCompleted é acionado.
Cuidado
É possível que o download seja concluído assim que a solicitação CancelAsync for feita, portanto Cancelled , talvez não reflita a solicitação de cancelamento. Isso é chamado de condição de corrida e é um problema comum na programação com multi-thread. Para saber mais sobre problemas de programação multi-thread, confira Práticas recomendadas de threading gerenciado.
Características do padrão assíncrono baseado em evento
O padrão assíncrono baseado em evento pode tomar várias formas, dependendo da complexidade das operações com suporte de uma classe específica. As classes mais simples podem ter um único método MethodNameAsync e um evento MethodNameCompleted correspondente. Classes mais complexas podem ter vários métodos MethodNameAsync , cada um com um evento MethodNameCompleted correspondente, bem como versões síncronas desses métodos. As classes podem, opcionalmente, dar suporte a cancelamento, relatório de progresso e resultados incrementais para cada método assíncrono.
Um método assíncrono também pode dar suporte a várias chamadas pendentes (várias invocações simultâneas), permitindo que seu código o chame várias vezes antes de concluir outras operações pendentes. Lidar corretamente com essa situação pode exigir que seu aplicativo acompanhe a conclusão de cada operação.
Exemplos do padrão assíncrono baseado em evento
Os componentes SoundPlayer e PictureBox representam implementações simples do padrão assíncrono baseado em evento. Os componentes WebClient e BackgroundWorker representam implementações mais complexas do Padrão Assíncrono Baseado em Evento.
Veja abaixo uma declaração de classe de exemplo que está em conformidade com o padrão:
Public Class AsyncExample
' Synchronous methods.
Public Function Method1(ByVal param As String) As Integer
Public Sub Method2(ByVal param As Double)
' Asynchronous methods.
Overloads Public Sub Method1Async(ByVal param As String)
Overloads Public Sub Method1Async(ByVal param As String, ByVal userState As Object)
Public Event Method1Completed As Method1CompletedEventHandler
Overloads Public Sub Method2Async(ByVal param As Double)
Overloads Public Sub Method2Async(ByVal param As Double, ByVal userState As Object)
Public Event Method2Completed As Method2CompletedEventHandler
Public Sub CancelAsync(ByVal userState As Object)
Public ReadOnly Property IsBusy () As Boolean
' Class implementation not shown.
End Class
public class AsyncExample
{
// Synchronous methods.
public int Method1(string param);
public void Method2(double param);
// Asynchronous methods.
public void Method1Async(string param);
public void Method1Async(string param, object userState);
public event Method1CompletedEventHandler Method1Completed;
public void Method2Async(double param);
public void Method2Async(double param, object userState);
public event Method2CompletedEventHandler Method2Completed;
public void CancelAsync(object userState);
public bool IsBusy { get; }
// Class implementation not shown.
}
A classe fictícia AsyncExample tem dois métodos, ambos compatíveis com invocações síncronas e assíncronas. As sobrecargas síncronas se comportam como qualquer chamada de método e executam a operação no thread de chamada; se a operação consumir tempo, pode haver um atrasa notável antes de a chamada retornar. As sobrecargas assíncronas iniciarão a operação em outro thread e retornarão imediatamente, permitindo que o thread de chamada continue enquanto a operação é executada "em segundo plano".
Sobrecargas de Método Assíncronas
Há potencialmente duas sobrecargas para as operações assíncronas: invocação única e invocação múltipla. Você pode distinguir essas duas formas por suas assinaturas de método: o formulário de invocação múltipla tem um parâmetro extra chamado userState. Esse formulário possibilita que seu código chame Method1Async(string param, object userState) várias vezes sem aguardar a conclusão de operações assíncronas pendentes. Se, por outro lado, você tentar chamar Method1Async(string param) antes de uma invocação anterior ser concluída, o método gerará um InvalidOperationException.
O userState parâmetro para as sobrecargas de invocação múltipla permite distinguir entre operações assíncronas. Você fornece um valor exclusivo (por exemplo, um GUID ou código de hash) para cada chamada Method1Async(string param, object userState)e, quando cada operação é concluída, seu manipulador de eventos pode determinar qual instância da operação gerou o evento de conclusão.
Acompanhamento de operações pendentes
Se você usar as sobrecargas de invocação múltipla, seu código precisará monitorar os objetos userState (IDs de tarefa) para as tarefas pendentes. Para cada chamada a Method1Async(string param, object userState), você normalmente gerará um novo objeto exclusivo userState e o adicionará a uma coleção. Quando a tarefa correspondente a esse userState objeto gerar o evento de conclusão, a implementação do método de conclusão irá examinar AsyncCompletedEventArgs.UserState e removê-lo da coleção. Usado dessa forma, o userState parâmetro assume a função de uma ID de tarefa.
Observação
Você deve ter o cuidado de fornecer um valor exclusivo para userState em suas chamadas para sobrecargas de invocação múltipla. IDs de tarefa não exclusivos farão com que a classe assíncrona lance um ArgumentException.
Cancelando operações pendentes
É importante poder cancelar operações assíncronas a qualquer momento antes de sua conclusão. As classes que implementam o Padrão Assíncrono baseado em evento terão um CancelAsync método (se houver apenas um método assíncrono) ou um método MethodNameAsyncCancel (se houver vários métodos assíncronos).
Os métodos que permitem várias invocações utilizam um userState parâmetro, que pode ser usado para acompanhar o tempo de vida de cada tarefa. CancelAsync usa um userState parâmetro, que permite cancelar tarefas pendentes específicas.
Métodos que dão suporte apenas a uma única operação pendente por vez, como Method1Async(string param), não são canceláveis.
Recebendo atualizações de progresso e resultados incrementais
Uma classe que adere ao Padrão Assíncrono baseado em evento pode, opcionalmente, fornecer um evento para acompanhar o progresso e os resultados incrementais. Isso normalmente será nomeado ProgressChanged ou MethodNameProgressChanged, e seu manipulador de eventos correspondente usará um ProgressChangedEventArgs parâmetro.
O manipulador de eventos do ProgressChanged evento pode examinar a ProgressChangedEventArgs.ProgressPercentage propriedade para determinar qual porcentagem de uma tarefa assíncrona foi concluída. Essa propriedade vai variar de 0 a 100 e pode ser usada para atualizar a Value propriedade de um ProgressBar. Se várias operações assíncronas estiverem pendentes, você poderá usar a ProgressChangedEventArgs.UserState propriedade para distinguir qual operação está relatando o progresso.
Algumas classes podem relatar resultados incrementais à medida que as operações assíncronas prossseguem. Esses resultados serão armazenados em uma classe que deriva de ProgressChangedEventArgs e aparecerão como propriedades na classe derivada. Você pode acessar esses resultados no manipulador de eventos do ProgressChanged evento, assim como acessaria a ProgressPercentage propriedade. Se várias operações assíncronas estiverem pendentes, você poderá usar a UserState propriedade para distinguir qual operação está relatando resultados incrementais.
Consulte também
- ProgressChangedEventArgs
- BackgroundWorker
- AsyncCompletedEventArgs
- Como usar componentes que dão suporte ao padrão assíncrono baseado em evento
- Como executar uma operação em segundo plano
- Como implementar um formulário que usa uma operação em segundo plano
- Padrão assíncrono baseado em evento (EAP)
- Práticas recomendadas para implementar o padrão assíncrono baseado em evento
- Decidindo quando implementar o padrão assíncrono baseado em evento