2009-05-15 10 views
4

J'ai passé beaucoup d'heures ce soir la lecture sur la mise en œuvre du modèle asynchrone basé sur les événementsQuand utiliser AsyncOperation et AsyncOperationManager

Malheureusement, je n'ai pas été en mesure de trouver des articles sur tout witting une classe prend uniquement en charge un appel asynchrone.

Chaque exemple que j'ai vu suppose qu'un appel de méthode sera appelé plus d'une fois et donc, devrait avoir un objet userState passé dans le MethodName Async

Vous verrez que MS fait mention de cette dans la troisième puce de cet article http://msdn.microsoft.com/en-us/library/ms228974(VS.80).aspx sous la rubrique "Exécution simultanée des opérations".

Mais je suis confus. Devrais-je utiliser des classes AsyncOperation et AsyncOperationManager pour avoir des fonctionnalités asynchrones où une méthode ne peut être appelée que par un thread à la fois?

Un lien serait aussi agréable :)

Merci

+0

langue/plate-forme? Je devine. NET, mais ajoutez un mot-clé, s'il vous plaît – Javier

Répondre

11

Tout d'abord, nous devons dire que la synchronisation le contexte est.
Le contexte de synchronisation est une classe qui détermine les opérations de thread à exécuter.
Les principales classes de contexte de synchronisation - SynchronizationContext et WindowsFormsSynchronizationContext - sont simplement des classes simples qui peuvent déléguer les opérations à d'autres threads.
La méthode SynchronizationContext.Post() délègue simplement une opération à un thread à partir d'un pool de threads (en utilisant la méthode ThreadPool.QueueUserWorkItem (...) en interne).
La méthode SynchronizationContext.Send() exécute simplement le délégué dans le même thread.
L'utilisation la plus fréquente de WindowsFormsSynchronizationContext est la suivante: WindowsFormsSynchronizationContext est défini en interne pour le thread graphique principal lorsque vous créez le formulaire principal de votre application. Plus tard, ce contexte de synchronisation est utilisé pour exécuter des délégués sur le même thread graphique principal. Donc, je vais conclure, contexte de synchronisation est une classe simple qui décide sur quel thread un délégué sera exécuté.

Revenons maintenant à la classe AsyncOperationManager.
Vous pouvez utiliser la classe AsyncOperationManager lorsque vous devez exécuter une opération sur un contexte de synchronisation. Le cotnext de synchronisation sur lequel l'opération sera exécutée peut être:

1) Le même contexte de synchronisation dans lequel vous appelez la méthode AsyncOperationManager.CreateOperation(), si le thread a un SynchronizationContext défini.
ou
2) Nouveau contexte de synchronisation (représenté par une nouvelle instance de la classe de base SynchronizationContext), si le contexte actuel de synchronisation n'a pas encore défini de contexte de synchronisation. L'instance de la classe de base SynchronizationContext, comme je l'ai déjà dit précédemment, va exécuter des délégués sur un thread à partir d'un pool de threads.

Fondamentalement, AsyncOperationManager est simplement une classe d'aide simple qui utilise les classes AsyncOperation et SynchronizationContext en interne.

Maintenant, à propos des scénarios d'utilisation.
Par exemple, dans votre thread graphique principal, vous créez une classe qui fournit des opérations asynchrones à l'aide d'un modèle asynchrone basé sur des événements (c'est-à-dire qu'il fournit des événements signalant la progression).
Vous souhaitez que vos gestionnaires d'événements soient exécutés dans le même thread graphique, de sorte que vous puissiez utiliser vos contrôles graphiques depuis les gestionnaires d'événements.
Dans ce cas, la méthode OperationAsync vous créez un objet AsyncOperation et le stocker pour une utilisation ultérieure:

public void OperationAsync(object arg1, object arg2, ...) 
{ 
    _asyncOperation = AsyncOperationManager.CreateOperation(null); 
    /* _asyncOperation object now captured current synchronization 
    context, which is WindowsFormsSynchronizationContext if you 
    run this method from GUI thread. */ 
    ... 
} 

Et lorsque l'opération terminée, vous lever événement OperationCompleted en utilisant la méthode AsyncOperation.Post(). Si vous exécutez la méthode AsyncOperationManager.CreateOperation() à partir du fil de l'interface graphique de votre application, les gestionnaires d'événements seront exécutés sur le même fil - à savoir sur votre thread principal GUI:

private void OnOperationCompleted(AsyncCompletedEventArgs e) 
{ 
    EventHandler<AsyncCompletedEventArgs> handler = OperationCompleted; 
    if(handler != null) 
    { 
    _asyncOperation.Post(
     delegate 
     { 
     handler(this, e); 
     }, 
     null); 

    _asyncOperation.OperationCompleted(); 
    } 
    .... 
} 
Questions connexes