2011-02-18 2 views
5

J'implémente une interface qui nécessite des implémentations des méthodes BeginDoSomething et EndDoSomething. Cependant, mon DoSomething n'est pas très long. Par souci de simplicité suppose DoSomething ne compare que deux variables et le retour si a> bComment créer un IAsyncResult qui se termine immédiatement?

Donc, mon BeginDoSomething devrait ressembler à:

protected override IAsyncResult BeginDoSomething(int a, int b, AsyncCallback callback, object state) 
{ 
    bool returnValue = a > b; 
    return ...; //what should I return here? 
    //The method actually already completed and I don't need to wait for anything 
} 

Je ne sais pas ce que je devrais revenir. Je n'implémente que BeginDoSomething parce que je le dois, pas parce que ma méthode est longue. Dois-je implémenter le mien IAsyncResult? Existe-t-il déjà une implémentation dans les bibliothèques .NET?

Répondre

3

Le hack façon de le faire est d'utiliser un délégué:

protected override IAsyncResult BeginDoSomething(int a, int b, AsyncCallback callback, object state) 
{ 
    bool returnValue = a > b; 
    Func<int,int,bool> func = (x,y) => x > y; 
    return func.BeginInvoke(a,b,callback,state); 
} 

L'inconvénient de cette approche, c'est tha Vous devez faire attention si deux threads appellent cette méthode simultanément, vous obtiendrez une erreur.

+0

Pas vraiment rapide mais difficile à discuter avec la simplicité. Omettez returnValue. Je ne vois pas l'erreur. –

+0

ce qui devrait être dans le 'EndDoSomething' alors? Je suis désolé, je suis très nouveau sur la programmation asynchrone –

+0

dans End * ce serait la même chose que func.BeginInvoke: IAsyncResult, donc vous déléguez la responsabilité à l'implémentation de Delegate. – Henrik

5

Ceci est un peu rapide et sale, mais vous pouvez mettre en œuvre une classe qui implémente IAsyncResult comme ceci:

public class MyAsyncResult : IAsyncResult 
    { 
     bool _result; 

     public MyAsyncResult(bool result) 
     { 
      _result = result; 
     } 

     public bool IsCompleted 
     { 
      get { return true; } 
     } 

     public WaitHandle AsyncWaitHandle 
     { 
      get { throw new NotImplementedException(); } 
     } 

     public object AsyncState 
     { 
      get { return _result; } 
     } 

     public bool CompletedSynchronously 
     { 
      get { return true; } 
     } 
    } 

Ensuite, utilisez dans votre BeginDoSomething comme ceci:

return new MyAsyncResult(a > b); 
+2

Je pense que la propriété 'AsyncWaitHandle' devrait renvoyer une référence à un * set *' ManualResetEvent' (ou similaire). Il est parfaitement raisonnable que les clients essaient d'attendre sur le handle, ce qui ne devrait pas provoquer une exception. – Ani

+0

Certes, nous pourrions le faire, mais comme un WaitHandle est un objet coûteux, il semble inutile de le créer quand cela ne sera ** jamais ** pertinent. –

+2

Le code manque l'appel de rappel, requis (sinon null). –

Questions connexes