Implementando o padrão assíncrono baseado em evento

Se estiver escrevendo uma classe com algumas operações que podem incorrer atrasos perceptíveis, considere a possibilidade de dar a ele funcionalidade assíncrono por meio da implementação de padrão assíncrono baseado em evento Visão geral sobre.

O padrão assíncrono baseado em eventoo fornece uma maneira padronizada para empacotar uma classe que tenha recursos assíncronos.Se implementada com classes auxiliares como AsyncOperationManager, sua classe irá funcionar corretamente sob qualquer modelo de aplicativo, incluindo ASP.NETAplicativos Windows Forms e do console.

Para obter um exemplo que implementa o padrão assíncrono baseado em evento, consulte Como: Um componente que oferece suporte ao implementar o padrão assíncrono baseado em evento.

Para operações assíncrono simples, você pode encontrar o BackgroundWorker componente adequado. Para obter mais informações sobre o BackgroundWorker, consulte Como: Executar uma operação no plano de fundo.

A lista a seguir descreve os recursos do padrão assíncrono baseado em evento discutidos neste tópico.

  • Oportunidades para Implementando o padrão assíncrono baseado em evento

  • Métodos assíncrono de nomeação

  • Opcionalmente, cancelamento de suporte

  • Opcionalmente, suporte a propriedade IsBusy

  • Opcionalmente, fornecer suporte para relatórios de andamento

  • Opcionalmente, fornecer suporte para retornar resultados incrementais

  • Manipulação de out e ref parâmetros em métodos

Oportunidades para Implementando o padrão assíncrono baseado em evento

Considere a implementação do padrão assíncrono com base em eventos quando:

  • Os clientes da sua classe não precisam WaitHandle e IAsyncResult objetos disponível para operações assíncrono, significando que sondagem e WaitAll ou WaitAny precisará ser criadas pelo cliente.

  • Você deseja que as operações assíncrono a serem gerenciado pelo cliente com o familiar evento / delegado modelo.

Qualquer operação é um candidato para uma implementação assíncrono, mas aqueles que pretende incorrer latências longas devem ser consideradas.Especialmente apropriadas são operações em que os clientes chamar um método e serão notificados após a conclusão, sem intervenção adicional necessária.Também apropriadas são operações que continuamente, executado periodicamente notificar os clientes de progresso, resultados incrementais ou alterações de estado.

Para mais informações sobre como decidir quando suportar o padrão assíncrono evento-based, consulte Decidindo quando implementar o padrão assíncrono com base em eventos.

Métodos assíncrono de nomeação

Para cada método síncrono MethodName para o qual você deseja fornecer uma contraparte assíncrono:

Definir um MethodNameAsync método que:

  • Retornavoid.

  • Aceita sistema autônomo parâmetros mesmos sistema autônomo a MethodName método.

  • Aceita várias chamadas.

Opcionalmente, defina um MethodNameAsync sobrecarga, idêntica ao MethodNameAsync, mas com um parâmetro adicional com valor de objeto, chamado userState. Se você estiver preparado para gerenciar várias chamadas simultâneas de seu método, caso em que o userState valor será entregue novamente para todos os manipuladores de eventos para distinguir invocações do método. Você também pode optar por fazer isso simplesmente sistema autônomo um local para armazenar o estado do usuário para recuperação posterior.

Para cada separado MethodNameAsync assinatura do método:

  1. Defina o seguinte evento no clsistema autônomos mesmo sistema autônomo o método:

    Public Event MethodNameCompleted As MethodNameCompletedEventHandler
    
    public event MethodNameCompletedEventHandler MethodNameCompleted;
    
  2. Defina as seguintes delegado e AsyncCompletedEventArgs. Isso provavelmente serão definidos fora da própria classe, mas no mesmo espaço para nome.

    Public Delegate Sub MethodNameCompletedEventHandler( _
        ByVal sender As Object, _
        ByVal e As MethodNameCompletedEventArgs)
    
    Public Class MethodNameCompletedEventArgs
        Inherits System.ComponentModel.AsyncCompletedEventArgs
    Public ReadOnly Property Result() As MyReturnType
    End Property
    
    public delegate void MethodNameCompletedEventHandler(object sender, 
        MethodNameCompletedEventArgs e);
    
    public class MethodNameCompletedEventArgs : System.ComponentModel.AsyncCompletedEventArgs
    {
        public MyReturnType Result { get; }
    }
    
    • Certifique-se de que o MethodNameCompletedEventArgs classe expõe seus membros sistema autônomo propriedades somente leitura e não sistema autônomo campos, sistema autônomo campos de impedir que vinculação de dados.

    • Não definir qualquer AsyncCompletedEventArgs-derivadas de classes para métodos que não produzirem resultados. Basta usar uma instância de AsyncCompletedEventArgs propriamente dito.

      Observação:

      É perfeitamente aceitável, quando apropriado, a reutilização de delegado e viável e AsyncCompletedEventArgs tipos. Neste csistema autônomoe a nomenclatura não será sistema autônomo consistente com o nome do método, desde uma determinada delegado e AsyncCompletedEventArgs não ser vinculado a um único método.

Opcionalmente, cancelamento de suporte

Se sua classe irá oferecer suporte a cancelamento de operações assíncrono, cancelamento deve ser exposto ao cliente, conforme descrito abaixo.Observe que há dois pontos de decisão que precisa ser alcançado antes de definir seu suporte a cancelamento:

  • Sua classe, incluindo futuros inclusões previstos, tem apenas uma operação assíncrono que oferece suporte ao cancelamento?

  • É possível as operações assíncrono que suportam o suporte ao cancelamento várias operações pendentes?Ou seja, faz o MethodNameAsync método levar um userState parâmetro, e permitir várias chamadas antes de qualquer concluir a aguardar?

Use as respostas a essas dois perguntas na tabela a seguir para determinar qual a assinatura de seu método de cancelamento deve ser.

Visual Basic

 

Várias operações simultâneas suportadas

Somente uma operação em uma time

Uma operação assíncrona em classe inteira

Sub MethodNameAsyncCancel(ByVal userState As Object)
Sub MethodNameAsyncCancel()

Várias operações assíncronas na classe

Sub CancelAsync(ByVal userState As Object)
Sub CancelAsync()

C#

 

Várias operações simultâneas suportadas

Somente uma operação em uma time

Uma operação assíncrona em classe inteira

void MethodNameAsyncCancel(object userState);
void MethodNameAsyncCancel();

Várias operações assíncronas na classe

void CancelAsync(object userState);
void CancelAsync();

Se você definir o CancelAsync(object userState) método, os clientes devem ter cuidadosos ao escolher seus valores de estado para torná-los capazes de fazer a distinção entre todos os métodos assíncronos invocados no objeto e não apenas entre todas as invocações de um único método assíncrono.

A decisão para nomear a única operação de async versão MethodNameAsyncCancel baseia-se em ser capaz de detectar mais com com facilidade o método em um ambiente de criação como o IntelliSense do Visual Studio.Isso agrupa membros relacionados e distingue-los de outros membros que não têm nada a ver com a funcionalidade assíncrono.Se você espera que pode haver operações assíncrono adicionais adicionadas em versões subseqüentes, é melhor definir CancelAsync.

Não defina vários métodos da tabela acima na mesma classe.Será que não faça sentido ou ele irá truncar a interface de classe com uma proliferação de métodos.

Esses métodos normalmente retornará imediatamente e a operação pode ou não pode cancelar realmente.No manipulador de eventos para o MethodNameCompleted evento, a MethodNameCompletedEventArgs objeto contém um Cancelled campo, que os clientes podem usar para determinar se o cancelamento ocorreu.

Obedecer à semântica de cancelamento descrita em Práticas recomendadas para implementar o padrão assíncrono com base em eventos.

Opcionalmente, suporte a propriedade IsBusy

Se sua classe não oferece suporte a várias chamadas simultâneas, considere a possibilidade de expor um IsBusy propriedade. Isso permite aos desenvolvedores determinar se um MethodNameAsync método está em execução sem capturar uma exceção a partir de MethodNameAsync método.

Obedecer ao IsBusy semântica descrita em Práticas recomendadas para implementar o padrão assíncrono com base em eventos.

Opcionalmente, fornecer suporte para relatórios de andamento

É freqüentemente desejável para uma operação assíncrono para relatar o andamento durante sua operação.O padrão assíncrono evento-based fornece uma diretriz para fazê-lo.

  • Opcionalmente, definir um evento a serem gerados por operação assíncrono e invocado em apropriadas thread.The ProgressChangedEventArgs objeto transporta um indicador de progresso com valor de inteiro deve ser entre 0 e 100.

  • Nomeie esse evento sistema autônomo segue:

    • ProgressChanged Se a classe possui várias operações assíncrono (ou deve crescer para incluir várias operações assíncrono em versões futuras); o

    • MethodNameProgressChanged se a classe tem uma única operação assíncrono.

    Esta opção de nomeação iguala que fez para o método de cancelamento, sistema autônomo descrito na seção opcionalmente suporte ao cancelamento.

Este evento deve usar o ProgressChangedEventHandler delegado a assinatura e o ProgressChangedEventArgs classe. Como alternativa, se um indicador de progresso mais específicas de domínio pode ser fornecido (para instância, leitura de bytes e total de bytes para uma operação de baixar), então, você deve definir uma classe derivada de ProgressChangedEventArgs.

Observe que há apenas um ProgressChanged ou MethodNameProgressChanged evento para a classe, independentemente do número de métodos assíncrono, que ele oferece suporte.Espera-se que os clientes para usar o userState objeto que é passado para o MethodNameAsync métodos para distinguir entre atualizações de andamento de várias operações simultâneas.

Pode haver situações em que oferecem suporte a várias operações de progresso e cada um retorna um indicador de andamento diferente.Neste caso, um único ProgressChanged evento não é apropriado, e você pode considerar a oferecer suporte a vários ProgressChanged eventos. Nesse caso usa um padrão de nomeação de MethodNameProgressChanged for each MethodNameAsync método.

Obedecer ao relatório de andamento semântica descrito Práticas recomendadas para implementar o padrão assíncrono com base em eventos.

Opcionalmente, fornecer suporte para retornar resultados incrementais

Às vezes, uma operação assíncrono pode retornar resultados incrementais antes de ser concluída.Há uma série de opções que podem ser usadas para oferecer suporte a esse cenário.Veja a seguir alguns exemplos.

Classe única operação

Se sua classe suporta apenas uma única operação assíncrono, e que a operação é capaz de retornar resultados incrementais, então:

  • Estender o ProgressChangedEventArgs Digite para transportar os dados resultantes incremental e definir um MethodNameProgressChanged evento com isso estendido dados.

  • Elevar este MethodNameProgressChanged evento quando houver um resultado incremental ao relatório.

Essa solução se aplica especificamente para uma classe única operação de assíncrona porque não há nenhum problema com o mesmo evento ocorrendo retornar resultados incrementais em "todas sistema autônomo operações", sistema autônomo oMethodNameProgressChanged evento faz.

Operação múltipla classe com resultados incrementais homogêneo

Nesse caso, sua classe oferece suporte a vários métodos assíncrono cada capazes de retornar resultados incrementais, e esses resultados incrementais todos têm o mesmo tipo de dados.

Siga o modelo descrito acima para classes de operação único, sistema autônomo o mesmo EventArgs estrutura funcionarão para todos sistema autônomo resultados incrementais. Definir um ProgressChanged evento em vez de um MethodNameProgressChanged evento, desde que ele se aplica aos métodos assíncrono múltiplos.

Operação de várias classe com resultados incrementais heterogêneos

Se sua classe oferece suporte a vários métodos assíncrono, cada um retorno de um tipo diferente de dados, você deve:

  • Separe seu resultado incremental relatórios a partir de seu relatório de andamento.

  • Definir um separado MethodNameProgressChanged evento com apropriado EventArgs para cada método assíncrono lidar com dados do resultado incremental do método.

Chamar esse manipulador de eventos no segmento apropriado conforme descrito em Práticas recomendadas para implementar o padrão assíncrono com base em eventos.

Manipulação de out e ref parâmetros em métodos

Embora o uso de out e ref é, em geral, desencorajado no .NET estrutura, aqui estão as regras a seguir quando eles estiverem presentes:

Dado um método síncrono MethodName:

  • out parâmetros para MethodName não deve ser parte de MethodNameAsync.Em vez disso, eles devem fazer parte de MethodNameCompletedEventArgs com o mesmo nome sistema autônomo seu parâmetro equivalente em MethodName (a menos que haja um nome mais apropriado).

  • ref parâmetros para MethodName deve ser exibido sistema autônomo parte de MethodNameAsynce sistema autônomo parte de MethodNameCompletedEventArgs com o mesmo nome sistema autônomo seu parâmetro equivalente em MethodName (a menos que haja um nome mais apropriado).

Por exemplo, dada:

Public Function MethodName(ByVal arg1 As String, ByRef arg2 As String, ByRef arg3 As String) As Integer
public int MethodName(string arg1, ref string arg2, out string arg3);

O método assíncrono e seus AsyncCompletedEventArgs classe teria esta aparência:

Public Sub MethodNameAsync(ByVal arg1 As String, ByVal arg2 As String)

Public Class MethodNameCompletedEventArgs
    Inherits System.ComponentModel.AsyncCompletedEventArgs
    Public ReadOnly Property Result() As Integer 
    End Property
    Public ReadOnly Property Arg2() As String 
    End Property
    Public ReadOnly Property Arg3() As String 
    End Property
End Class
public void MethodNameAsync(string arg1, string arg2);

public class MethodNameCompletedEventArgs : System.ComponentModel.AsyncCompletedEventArgs
{
    public int Result { get; };
    public string Arg2 { get; };
    public string Arg3 { get; };
}

Consulte também

Tarefas

Como: Um componente que oferece suporte ao implementar o padrão assíncrono baseado em evento

Como: Executar uma operação no plano de fundo

Como: Implementar um formulário que usa uma operação de plano de fundo

Conceitos

Decidindo quando implementar o padrão assíncrono com base em eventos

Práticas recomendadas para implementar o padrão assíncrono com base em eventos

Referência

ProgressChangedEventArgs

AsyncCompletedEventArgs

Outros recursos

Vários segmentos de programação com o padrão assíncrono baseado em eventoo