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

O padrão assíncrono baseado em eventoo fornece uma maneira eficiente de expor comportamento assíncrono em classes, semântica de eventoos e o delegado familiar.Para implementar padrão assíncrono baseado em evento, é necessário seguir alguns requisitos específicos de comportamentos.As seções a seguir descrevem os requisitos e diretrizes, você deve considerar quando você implementar uma classe que segue o padrão assíncrono baseado em evento.

Para obter uma visão geral, consulte Implementando o padrão assíncrono baseado em evento.

A lista a seguir mostra as práticas recomendadas discutidas neste tópico:

  • Necessário garantias comportamentais

  • Conclusão

  • Concluída evento e evento arg.

  • Executando simultaneamente operações

  • Acessando resultados

  • Relatório de andamento

  • Implementação IsBusy

  • Cancelamento

  • Erros e exceções

  • Threading e contextos

  • Diretrizes

Necessário garantias comportamentais

Se você implementar a evento - com base padrão assíncrono, você deve fornecer um número de garantias para garantir que sua classe se comportará corretamente e os clientes da sua classe podem contar com tal comportamento.

Conclusão

Sempre chamar o MethodNameCompleted manipulador de eventos quando você tem a conclusão bem-sucedida, um erro ou um cancelamento.Aplicativos nunca devem encontrar uma situação em que eles permanecem ociosos e conclusão nunca ocorre.Uma exceção a essa regra é se a operação assíncrono próprio ele projetado para que ela nunca seja concluída.

Concluída evento e evento arg.

Para cada separado MethodNameAsync método, aplicar os requisitos de design a seguir:

  • Definir um MethodNameCompleted evento da mesma classe do método.

  • Definir um EventArgs classe e o delegado fornecido para o MethodNameCompleted evento que deriva de AsyncCompletedEventArgs classe. O nome de classe padrão deve ser do formulário MethodNameCompletedEventArgs.

  • Certifique-se de que o EventArgs é específico de valores de retorno da classe a MethodName método.Quando você usa o EventArgs classe, você nunca deve exigir que os desenvolvedores a converter o resultado.

    O exemplo de código a seguir mostra a implementação de mercadoria e ruim desse requisito de design respectivamente.

[C#]

// Good design
private void Form1_MethodNameCompleted(object sender, xxxCompletedEventArgs e) 
{ 
    DemoType result = e.Result;
}

// Bad design
private void Form1_MethodNameCompleted(object sender, MethodNameCompletedEventArgs e) 
{ 
    DemoType result = (DemoType)(e.Result);
}

Executando simultaneamente operações

  • Se a sua classe oferecer suporte a várias chamadas simultâneas, ative o desenvolvedor rastrear cada chamada separadamente, definindo o MethodNameAsync sobrecarregar esse parâmetro de estado obtém um valor de objeto ou ID, chamado de tarefasuserSuppliedState. Este parâmetro deve ser sempre o último parâmetro no MethodNameAsyncassinatura do método .

  • Se sua classe define o MethodNameAsync sobrecarga que aceita um parâmetro com valor de objeto de estado ou identificação da tarefa, certifique-se de controlar o tempo de vida da operação com essa identificação da tarefa e não se esqueça de fornecê-lo de volta para o manipulador de conclusão.Há classes auxiliares disponível para ajudá-lo.Para obter mais informações sobre o gerenciamento de simultaneidade, consulte Demonstra Passo a passo: Um componente que oferece suporte ao implementar o padrão assíncrono baseado em evento.

  • Se sua classe define o MethodNameAsync método sem o parâmetro de estado e ele não oferecer suporte a várias chamadas simultâneas, certifique-se de que qualquer tentativa de chamar MethodNameAsync antes do anteriorMethodNameAsync invocação tem concluída gera um InvalidOperationException.

  • Em geral, não aumente uma exceção se o MethodNameAsync método sem o userSuppliedState parâmetro é chamado várias vezes para que haja várias operações pendentes. Você pode elevar uma exceção quando sua classe explicitamente não é possível lidar com essa situação, mas suponha que os desenvolvedores podem manipular esses vários retornos de chamadas indistinguíveis

Acessando resultados

Relatório de andamento

  • Suporte a relatórios de andamento, se possível.Isso permite que os desenvolvedores de proporcionar uma melhor experiência de usuário de aplicativo quando eles usam a classe.

  • Se você implementar um ProgressChanged/MethodNameProgressChanged evento, garantir que não haja nenhum tais eventos disparados para uma determinada operação assíncrono depois MethodNameCompleted evento que foi gerado.

  • Se o padrão ProgressChangedEventArgs está sendo preenchido, certifique-se de que o ProgressPercentage sempre podem ser interpretados sistema autônomo uma porcentagem. A porcentagem não precisa ser precisos mas ele deve representar uma porcentagem.Se sua métrica de relatório de andamento deve ser algo Outros que uma porcentagem derivar uma classe do ProgressChangedEventArgs classe e sair ProgressPercentage em 0. Evite usar uma métrica de relatório diferentes de uma porcentagem.

  • Certifique-se de que o ProgressChanged evento é gerado no segmento apropriado e em apropriadas time do ciclo de vida dos aplicativos. Para obter mais informações, consulte a seção Threading e contextos.

Implementação IsBusy

  • Não exponha um IsBusy propriedade se sua classe oferece suporte a várias chamadas simultâneas. Por exemplo, proxies de serviço Web XML não expõem um IsBusy propriedade pois suportam várias chamadas simultâneas de métodos assíncrono.

  • The IsBusy propriedade deve retornar true Depois que o MethodNameAsync método foi chamado e antes do MethodNameCompleted evento que foi gerado.Caso contrário, ele deverá retornar false. The BackgroundWorker e WebClient componentes são exemplos de classes que expõem um IsBusy propriedade.

Cancelamento

  • Suporte ao cancelamento, se possível.Isso permite que os desenvolvedores de proporcionar uma melhor experiência de usuário de aplicativo quando eles usam a classe.

  • No caso de cancelamento, definido a Cancelled sinalizar na AsyncCompletedEventArgs objeto.

  • Certifique-se de que qualquer tentativa de acessar o resultado lança um InvalidOperationException informando que a operação foi cancelada. Use o AsyncCompletedEventArgs.RaiseExceptionIfNecessary método para executar essa verificação.

  • Certifique-se de que chamadas ao método cancelamento sempre retornam com êxito e nunca elevar uma exceção.Em geral, um cliente não é notificado se uma operação é realmente pode ser cancelada a qualquer momento e não é notificado de um cancelamento emitido anteriormente foi bem-sucedida.No entanto, o aplicativo sempre receberá notificação quando um cancelamento foi bem-sucedida, porque o aplicativo tem participação no status de conclusão.

  • Aumentar o MethodNameCompleted evento quando a operação foi cancelada.

Erros e exceções

  • Capturar todas as exceções que ocorrem na operação assíncrono e conjunto o valor de AsyncCompletedEventArgs.Error propriedade para essa exceção.

Threading e contextos

Para a operação correta da sua classe, é essencial que os manipuladores de eventos do cliente são chamados no thread correto ou contexto para o modelo de determinado aplicativo, incluindo ASP.NET e aplicativos Windows Forms. Duas classes auxiliares importantes são fornecidos para garantir que sua classe assíncrono se comporta corretamente sob qualquer modelo de aplicativo: AsyncOperation e AsyncOperationManager.

AsyncOperationManager Fornece um método, CreateOperation, que retorna um AsyncOperation. O MethodNameAsync chamadas de método de CreateOperation e sua classe usa o retornado AsyncOperation para controlar o tempo de vida de tarefa assíncrono.

Para relatar o andamento e resultados incrementais conclusão para o cliente, ligue para o Post e OperationCompleted métodos de AsyncOperation. AsyncOperation é responsável pelo marshaling de chamadas para o cliente evento manipuladores no thread correto ou contexto.

Observação:

Você pode contornar essas regras se você deseja explicitamente ir com a diretiva do modelo de aplicativo, mas ainda se beneficiar das vantagens de usar o padrão assíncrono com base em eventos.Por exemplo, talvez seja conveniente uma classe operando em Windows Forms sem segmentação.Você pode criar uma classe segmentada disponível, desde que sistema autônomo desenvolvedores compreendam sistema autônomo restrições implícitas.Aplicativos de console não sincronizar a execução de Post chamadas. Isso pode causar ProgressChanged eventos de ser aumentado para fora de ordem. Se você desejar ter execução de serializadoPost chamadas, implementar e instalar um System.Threading.SynchronizationContext classe.

Para obter mais informações sobre como usar AsyncOperation e AsyncOperationManager Para ativar as operações assíncrono, consulte Demonstra Passo a passo: Um componente que oferece suporte ao implementar o padrão assíncrono baseado em evento.

Diretrizes

  • O ideal é que cada chamada do método sejam independente de outras pessoas.Você deve evitar o acoplamento invocações com recursos compartilhados.Se recursos estiverem para ser compartilhado entre invocações, precisará fornecer um mecanismo de uma sincronização adequada em sua implementação.

  • Designs que requerem que o cliente implementar a sincronização são desencorajados.Por exemplo, você poderia ter um método assíncrono que recebe um objeto estático global sistema autônomo um parâmetro; várias chamadas simultâneas de tal um método podem resultar em corrupção de dados ou deadlocks.

  • Se você implementar um método com a sobrecarga de invocação múltiplo (userState na assinatura), sua classe precisará gerenciar uma coleção de estados do usuário, ou de identificações de tarefas e suas operações pendentes correspondente. Essa coleção deve ser protegida com lock regiões, porque as várias chamadas adicionar e remover userState objetos na coleção.

  • Considere a reutilização de CompletedEventArgs classes onde adequado e viável. Nesse caso, o nome não é consistente com o nome do método, porque um delegado determinado e EventArgs tipo não estão ligadas a um único método. No entanto, forçar os desenvolvedores a converter o valor recuperados de uma propriedade no EventArgs nunca é aceitável.

  • Se você estiver criando uma classe que deriva de Component, não implementar e instalar seus próprios SynchronizationContext classe. Modelos de aplicativos, componentes não controlam o SynchronizationContext que é usado.

  • Ao usar multithreading de qualquer tipo, você potencialmente expor você mesmo a bugs muito sérios e complexos.Antes de implementar qualquer solução que usa multithreading, consulte Gerenciado Threading práticas recomendadas .

Consulte também

Tarefas

Como: Use os componentes que suportam o padrão assíncrono baseado em evento

Demonstra Passo a passo: Um componente que oferece suporte ao implementar o padrão assíncrono baseado em evento

Conceitos

Implementando o padrão assíncrono baseado em evento

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

AsyncOperation

AsyncOperationManager

AsyncCompletedEventArgs

ProgressChangedEventArgs

BackgroundWorker

Outros recursos

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