Modelo de programação assíncrona (APM)
Uma operação assíncrona que utiliza o padrão de design IAsyncResult é implementada como dois métodos chamados BeginOperationName
e EndOperationName
que começam e terminam a operação assíncrona OperationName, respectivamente. Por exemplo, a classe FileStream fornece os métodos BeginRead e EndRead para ler os bytes de um arquivo de forma assíncrona. Esses métodos implementam a versão assíncrona do método Read.
Observação
A partir do .NET Framework 4, a Biblioteca de Paralelismo de Tarefas fornece um novo modelo de programação paralela e assíncrona. Para saber mais, confira Biblioteca de Paralelismo de Tarefas (TPL) e Padrão Assíncrono Baseado em Tarefa (TAP).
Depois de chamar BeginOperationName
, um aplicativo pode continuar a executar as instruções no thread de chamada, enquanto a operação assíncrona ocorre em um thread diferente. Cada chamada para BeginOperationName
, o aplicativo também deve chamar EndOperationName
para obter os resultados da operação.
Começando uma operação assíncrona
O método BeginOperationName
inicia a operação assíncrona OperationName e retorna um objeto que implementa a interface IAsyncResult. Os objetos IAsyncResult armazenam as informações sobre uma operação assíncrona. A tabela a seguir mostra informações sobre uma operação assíncrona.
Membro | DESCRIÇÃO |
---|---|
AsyncState | Um objeto específico do aplicativo opcional que contém informações sobre a operação assíncrona. |
AsyncWaitHandle | Um WaitHandle que pode ser usado para bloquear a execução do aplicativo até que a operação assíncrona seja concluída. |
CompletedSynchronously | Um valor que indica se a operação assíncrona foi concluída no thread usado para chamar BeginOperationName em vez de concluir em um thread ThreadPool separado. |
IsCompleted | Um valor que indica se a operação assíncrona foi concluída. |
Um método BeginOperationName
usa qualquer parâmetro declarado na assinatura da versão síncrona do método que é passado por valor ou referência. Os parâmetros de saída não são parte da assinatura do método BeginOperationName
. A assinatura do método BeginOperationName
também inclui dois parâmetros adicionais. O primeiro deles define um delegado AsyncCallback que faz referência a um método que é chamado quando a operação assíncrona é concluída. O chamador pode especificar null
(Nothing
no Visual Basic) se não desejar um método chamado quando a operação for concluída. O segundo parâmetro adicional é um objeto definido pelo usuário. Esse objeto pode ser usado para passar informações de estado específico do aplicativo para o método invocado quando a operação assíncrona é concluída. Se um método BeginOperationName
usar parâmetros adicionais específicos da operação, como uma matriz de bytes para armazenar os bytes lidos de um arquivo, o AsyncCallback e o objeto de estado do aplicativo serão os últimos parâmetros da assinatura de método BeginOperationName
.
BeginOperationName
retorna o controle para o thread de chamada imediatamente. Se o método BeginOperationName
gerar exceções, as exceções serão geradas antes de a operação assíncrona ser iniciada. Se o método BeginOperationName
gerar exceções, o método de retorno de chamada não será invocado.
Encerrando uma operação assíncrona
O método EndOperationName
termina a operação assíncrona OperationName. O valor retornado do método EndOperationName
é do mesmo tipo retornado pela sua contraparte síncrona e é específico para a operação assíncrona. Por exemplo, o método EndRead retorna o número de bytes lidos de um FileStream e o método EndGetHostByName retorna um objeto IPHostEntry que contém informações sobre um computador host. O método EndOperationName
usa qualquer parâmetro declarado de referência na assinatura da versão síncrona do método. Além dos parâmetros do método síncrono, o método EndOperationName
também inclui um parâmetro IAsyncResult. Os chamadores devem passar a instância retornada pela chamada correspondente para BeginOperationName
.
Se a operação assíncrona representada pelo objeto IAsyncResult não tiver sido concluída quando EndOperationName
for chamado, EndOperationName
bloqueará o thread de chamada até que a operação assíncrona seja concluída. As exceções geradas pela operação assíncrona são geradas do método EndOperationName
. O efeito da chamada para o método EndOperationName
várias vezes com o mesmo IAsyncResult não é definido. Da mesma forma, chamar o método EndOperationName
com um IAsyncResult que não foi retornado pelo método Begin relacionado também não será definido.
Observação
Para qualquer um dos cenários indefinidos, os implementadores devem considerar a geração de InvalidOperationException.
Observação
Os implementadores deste padrão de design devem notificar o chamador de que a operação assíncrona está concluída, definindo IsCompleted como true, chamando o método de retorno de chamada assíncrono (se tiver sido especificado) e sinalizando o AsyncWaitHandle.
Os desenvolvedores de aplicativos tem várias opções de design para acessar os resultados da operação assíncrona. A opção correta depende se o aplicativo tem instruções que podem ser executadas enquanto a operação é concluída. Se um aplicativo não puder executar trabalho adicional até que ele receba os resultados da operação assíncrona, o aplicativo deverá ser bloqueado até que os resultados estejam disponíveis. Para bloquear até que uma operação assíncrona seja concluída, você poderá usar uma das seguintes abordagens:
Chamar
EndOperationName
do thread principal do aplicativo, bloqueando a execução do aplicativo até que a operação seja concluída. Veja um exemplo que ilustra essa técnica em Bloqueando a execução de um aplicativo encerrando uma operação assíncrona.Use o AsyncWaitHandle para impedir a execução do aplicativo até que uma ou mais operações sejam concluídas. Veja um exemplo que ilustra essa técnica em Bloqueando a execução de um aplicativo com um AsyncWaitHandle.
Os aplicativos que não precisarem ser bloqueados enquanto a operação assíncrona é concluída podem usar uma das seguintes abordagens:
Sondagem de status de conclusão da operação, verificando a propriedade IsCompleted periodicamente e chamando
EndOperationName
quando a operação for concluída. Veja um exemplo que ilustra essa técnica em Sondagem do status de uma operação assíncrona.Use um delegado AsyncCallback para especificar um método a ser invocado quando a operação for concluída. Veja um exemplo que ilustra essa técnica em Usar um representante AsyncCallback para finalizar uma operação assíncrona.