2009-05-18 10 views
13

Je cherche à ajouter une certaine flexibilité à une classe que j'ai créée qui établit une connexion à un hôte distant et effectue ensuite un échange d'informations (une poignée de main). L'implémentation actuelle fournit une fonction Connect qui établit la connexion, puis bloque l'attente sur un ManualResetEvent jusqu'à ce que les deux parties aient terminé l'établissement de la liaison.Qu'est-ce qu'une implémentation correcte de l'interface IAsyncResult?

Voici un exemple de ce qui appelle ma classe ressemble à:

// create a new client instance 
ClientClass cc = new ClientClass("address of host"); 
bool success = cc.Connect(); // will block here until the 
           // handshake is complete 
if(success) 
{ 

} 

..et est ici une simplificatrice vue de haut niveau de ce que la classe fait en interne:

class ClientClass 
{ 
    string _hostAddress; 
    ManualResetEvent _hanshakeCompleted; 
    bool _connectionSuccess; 

    public ClientClass(string hostAddress) 
    { 
     _hostAddress = hostAddress;    
    } 

    public bool Connect() 
    { 
     _hanshakeCompleted = new ManualResetEvent(false);    
     _connectionSuccess = false; 

     // start an asynchronous operation to connect 
     // ... 
     // ... 

     // then wait here for the connection and 
     // then handshake to complete 
     _hanshakeCompleted.WaitOne(); 

     // the _connectionStatus will be TRUE only if the 
     // connection and handshake were successful 
     return _connectionSuccess; 
    } 

    // ... other internal private methods here 
    // which handle the handshaking and which call 
    // HandshakeComplete at the end 

    private void HandshakeComplete() 
    { 
     _connectionSuccess = true; 
     _hanshakeCompleted.Set(); 
    } 
} 

Je suis à la recherche dans la mise en œuvre du .NET Classic Async Pattern pour cette classe. Ce faisant, je fournirais les fonctions BeginConnect et EndConnect, et permettre aux utilisateurs de la classe d'écrire du code comme ceci:

ClientClass cc = new ClientClass("address of host"); 
cc.BeginConnect(new AsyncCallback(ConnectCompleted), cc); 
// continue without blocking to this line 

// .. 

void ConnectCompleted(IAsyncResult ar) 
{ 
    ClientClass cc = ar.AyncState as ClientClass; 
    try{ 
     bool success = cc.EndConnect(ar); 
     if(success) 
     { 
      // do more stuff with the 
      // connected Client Class object 
     } 
    } 
    catch{ 
    } 
} 

Afin d'être en mesure de fournir cette API je dois créer une classe qui implémente la Interface IAsyncResult à renvoyer par la fonction BeginConnect et à transmettre respectivement dans la fonction EndConnect. Maintenant, ma question est: Quelle est la bonne façon d'implémenter l'interface IAsyncResult dans une classe? Une solution évidente serait de créer un délégué avec une signature correspondante pour la fonction Connect, puis d'appeler ce délégué de manière asynchrone en utilisant BeginInvoke - EndInvoke mais ce n'est pas ce que je recherche (ce n'est pas très efficace). J'ai une idée approximative de comment je pourrais le faire mais après avoir jeté un coup d'oeil dans le cadre de .NET à la façon dont ils mettent en application ce modèle dans quelques endroits j'ai estimé qu'il serait sage de demander et voir si quelqu'un a fait ceci avec succès Alors, quels sont les domaines problématiques à accorder une attention particulière.

Merci!

Répondre

1

Vous avez également de nombreuses implémentations dans la BCL (par ex. System.Runtime.Remoting.Messaging.AsyncResult) - utiliser un réflecteur ou la source de référence pour les vérifier.