2011-01-17 22 views
6

Uso di .Net 4.0. Ho un codice che tenta di aprire una connessione usando BeginConnect e un callback. Se l'utente tenta di interrompere la programmazione nei prossimi momenti, provo a disconnetterti. A quel punto ho impostato un flag per indicare se è necessario chiamare EndConnect dal callback. Se il flag è impostato su false, salterò l'EndConnect perché il socket è stato cestinato comunque.Cosa succede se non si chiama mai Socket.EndConnect?

A questo punto, l'utente può provare a connettersi immediatamente. Non vedo succedere questo, ma nel caso. Ora viene creato un nuovo socket e viene richiamato BeginConnect.

Va bene non chiamare mai il metodo EndConnect?

risposta

3

In tutti i casi (tranne uno [1]) una chiamata a BeginZZZ bisogno di un corrispondente EndZZZZ.

In caso contrario, le risorse non gestite verranno divulgate e molto probabilmente l'azione ZZZZ non verrà completata correttamente — potenzialmente corrompendo in seguito ulteriori utilizzi di ZZZZ.

I socket sono piuttosto robusti contro l'abuso (lo stack IP deve gestire guasti di rete e pacchetti fuori servizio), ma ciò non lo rende una buona pratica.

Se si sta utilizzando un flag per tenere traccia dello "spegnimento", è meglio chiamare EndConnect e quindi chiudere immediatamente il socket. Dopo tutto, la connessione potrebbe fallire e non è necessario scollegare (EndConnect genera SocketException). Qualcosa di simile:

mySocket.BeginConnect(address, port, ia => { 
    if (shuttingDown) { 
    try { 
     mySocket.EndConnect(ia); 
     mySocket.BeginDisconnect(false, iaa = { 
     try { 
      mySocket.EndDisconnect(iaa); 
     } catch (Exception) { /* Ignore */ } 
     }, null); 
    } catch (SocketException) { /* Ignore */ } 
    } else { 
    // Normal connection handling 
    } 
}, null); 

Anche utilizzando la disconnessione asincrona per evitare il blocco lì.


[1] L'eccezione è Control.BeginInvoke in WinForms, dove l'eccezione è esplicitamente documentata.

+0

@Richard. Grazie per la risposta. Ho provato il tuo approccio ma continuo ad avere eccezioni su AsyncResult che non è lo stesso dalla corrispondente chiamata di inizio. Mi sono imbattuto nel blog di qualcuno che dice che dovremmo memorizzare in cache AsyncResult e verificare se è lo stesso prima di fare qualsiasi cosa. Ciò sembra azzardato e mi lascia indietro comunque al punto di partenza. Solo ignorando la cosa. – uriDium

+0

@Richard. Ok, wow. Il MSDN è molto carente e lavato su un paio di cose. In primo luogo, afferma: È possibile creare un metodo di callback che implementa il delegato AsyncCallback e passare il suo nome al metodo BeginConnect. Che suona davvero come se fosse facoltativo. Quindi il prossimo paragrafo afferma: Il metodo di callback dovrebbe richiamare il metodo EndConnect. Mi hanno appena detto che è opzionale ora mi stanno dicendo che dovrei chiamare EndConnect. Non posso chiamare EndConnect se "facoltativamente" l'ho escluso. Tuttavia: questa parte mi ha dato la speranza: per annullare una chiamata in sospeso al metodo BeginConnect, chiudi il socket. – uriDium

+0

@uriDium: il callback è facoltativo, ma non chiama 'EndConnect'. Invece è possibile attendere il 'IAsyncResult' restituito da' BeginConnect' (o eseguire il polling della sua proprietà 'IsCompleted') e quindi chiamare' EndConnect' - tutto senza usare la callback. Riepilogo: deve essere chiamato 'EndConnect', ma questo non deve essere all'interno del delegato passato a' BeginConnect'. – Richard

Problemi correlati