Sto provando a connettermi al mio server con una combinazione TcpClient.BeginConnect/TcpClient.EndConnect
. Tuttavia, alcune cose non funzionano come dovrebbero.TcpClient.EndConnect genera NullReferenceException quando il socket è chiuso
Lo scenario è il seguente:
- Chiama per il
TcpClient.BeginConnect
- Server è volutamente non in linea (a scopo di test) - quindi nessun collegamento può essere fatto.
- Chiudo l'applicazione (
client.Close()
viene chiamato nel processo che closes the socket which in turn stops the async operation) TcpClient
connessione metodo di callback accade dandoIAsyncResult
- chiamata al metodo
TcpClient.EndConnect
con il datoIAsyncResult
NullReferenceException
avviene suEndConnect
(?)- Poiché l'ultimo modulo (finestra) è stato chiuso, l'app dovrebbe uscire, tuttavia non t, almeno non fino al completamento dell'operazione
BeginConnect
(il che è strano, poiché la richiamata è già stata richiamata).
Quello che succede qui è che un NullReferenceException
e 'colto. Come puoi vedere dall'immagine sopra, né client
né ar
sono null
. Il problema è che il MSDN documentation for the EndConnect non menziona il caso in cui viene generata questa eccezione.
Quindi, in pratica, non ho idea di cosa stia succedendo. Il problema è che sono costretto ad aspettare che l'app si chiuda (come se l'operazione di connessione fosse ancora in attesa di un timeout). Se un server è online, collega e scollega semplicemente.
CosaNullReferenceException
in questo contesto significa? Come evitare l'operazione BeginConnect
per bloccare la chiusura dell'applicazione nel caso in cui la connessione non possa essere stabilita?
Note aggiuntive (richiesto in commenti):
Ecco il codice per creare il client (client è una variabile membro:
public void Connect()
{
try
{
lock (connectionAccess)
{
if (State.IsConnectable())
{
// Create a client
client = new TcpClient();
client.LingerState = new LingerOption(false, 0);
client.NoDelay = true;
State = CommunicationState.Connecting;
client.BeginConnect(address, port, onTcpClientConnectionEstablished, null);
}
else
{
// Ignore connecting request if a connection is in a state that is not connectable
}
}
}
catch
{
Close(true);
}
}
anche il metodo close:
public void Close(bool causedByError)
{
lock (connectionAccess)
{
// Close the stream
if (clientStream != null)
clientStream.Close();
// Close the gateway
if (client != null)
client.Close();
// Empty the mailboxes
incomingMailbox.Clear();
outgoingMailbox.Clear();
State = causedByError ? CommunicationState.CommunicationError : CommunicationState.Disconnected;
}
}
Does InnerException fornisce ulteriori informazioni su cosa fosse NULL? – Tremmors
@Tremmors Nope. InnerException è nullo. Nessun aiuto da StackTrace (onTcpClientConnectionEstablished> EndConnect). :( –
Sì, chiaramente un bug del framework Nel caso in cui il TcpClient venga chiuso prima che venga chiamato EndConnect(), si suppone che lanci ObjectDisposedException. Sembrerebbe ottenere NullReferenceException invece la prima o due volte, quindi inizierà a lanciare ObjectDisposedException Come previsto, ti suggerisco di gestirlo nello stesso modo in cui avresti dovuto eseguire ObjectDisposedException (cioè "timeout della connessione/errore/qualsiasi altra ragione hai chiamato Close()"). Tuttavia, non so se potrebbero esserci perdite di risorse qui dal momento che EndConnect() non sta completando Probabilmente nulla che il GC non possa gestire. :) – Tom