2009-11-09 5 views
1

Disons que j'ai le code qui utilise le modèle de programmation asynchrone, à savoir qu'il fournit les méthodes suivantes en tant que groupe qui peut être utilisé de manière synchrone ou asynchrone:Conversion de modèle de programmation asynchrone (méthodes Begin/End) en modèle asynchrone basé sur des événements?

public MethodResult Operation(<method params>); 

public IAsyncResult BeginOperation(<method params>, AsyncCallback callback, object state); 
public MethodResult EndOperation(IAsyncResult ar); 

Ce que je veux faire est de terminer ce code avec un montant supplémentaire couche qui transformera dans le modèle asynchrone piloté par événement, comme ceci:

public void OperationAsync(<method params>); 
public event OperationCompletedEventHandler OperationCompleted; 
public delegate void OperationCompletedEventHandler(object sender, OperationCompletedEventArgs e); 

quelqu'un at-il des directives (ou les liens vers ces conseils) sur la façon d'y parvenir?

Répondre

2

Voir "Async without the pain" pour des commentaires à ce sujet; le code fourni utilise une approche de rappel, mais les événements seraient assez faciles si vous le déposez sur une instance.

public static void RunAsync<T>(
    Func<AsyncCallback, object, IAsyncResult> begin, 
    Func<IAsyncResult, T> end, 
    Action<Func<T>> callback) { 
    begin(ar => { 
     T result; 
     try { 
      result = end(ar); // ensure end called 
      callback(() => result); 
     } catch (Exception ex) { 
      callback(() => { throw ex; }); 
     } 
    }, null); 
} 
+0

(j'ajouterais un exemple, mais entraînerais la sortie de la couverture) –

+0

Intéressant - ce style de code ressemble beaucoup à la bibliothèque parallèle de tâches. –

+0

Retour à la réception brièvement ... dans la signature au moins, il n'est pas loin comment F # fonctionne sous le capot, donc je pense qu'il y aura des similitudes. –

2

Vous pouvez utiliser l'encapsuleur avec la bibliothèque AsyncFunc.

http://asyncfunc.codeplex.com

Le code ressemblerait à ceci:

public class Original 
{ 
    public ResultType Operation(ParamType param){...} 
    public IAsyncResult BeginOperation(ParamType param, AsyncCallback callback, object state){...} 
    public ResultType EndOperation(IAsyncResult ar){...} 
} 

public class Wrapper 
{ 
    private AsyncFunc<ParamType, ResultType> _operation; 
    private Original _original; 

    public Wrapper(Original original) 
    { 
     _original = original; 
     _operation = AsyncFunc<ParamType, ResultType>(_original.Operation); 
    } 

    public ResultType Operation(ParamType param) 
    { 
     return _original.Operation(param); 
    } 

    public void OperationAsync(ParamType param) 
    { 
     _operation.InvokeAsync(param) 
    } 

    public event AsyncFuncCompletedEventHandler<ResultType> OperationCompleted  
     { 
     add { _operation.Completed += value; } 
     remove { _operation.Completed -= value; } 
    } 
} 

Notez que dans cette approche, vous ne pas besoin de définir délégué gestionnaire d'événements et de classe argument événement personnalisé. Ils peuvent être substitués par AsyncFunc types génériques:

OperationCompletedEventArgs -> ResultType 
OperationCompletedEventHandler -> AsyncFuncCompletedEventHandler<ResultType> 

Pour les scénarios les plus avancés vont à AsyncFunc page d'accueil. Il y a des vidéos et des échantillons.

Questions connexes