8
votes

Tcpclient.endconnect lance nullreferenceException lorsque la prise est fermée

J'essaie de vous connecter à mon serveur avec un tcpclient.beginconnect / tcpclient.endconnect combo. Cependant, certaines choses ne fonctionnent pas comme elles le devraient.

Le scénario est comme suit:


4 commentaires

Est-ce que l'Infurexception donne-t-il plus d'informations sur ce qui était NULL?


@Tremmors Nope. InnerException est null. Aucune aide de la StackTrace aussi (OncpClientConnectionStablied> endconnect). :(


Oui, clairement un bug-cadre. Dans le cas où le Tcpclient est fermé avant que l'endconnexion () est appelé, il est censé lancer ObjectDisposedException. Je semble obtenir NullReferenceException à la place du premier ou deux fois, alors il commencera à lancer ObjectDisposedException comme prévu. Je vous suggère de manipuler simplement de la même chose que vous l'obtiendriez (c'est-à-dire que vous avez choisi / quelle que soit l'échec / quelle que soit autre raison que vous avez appelé étroite () »). Cependant, je ne sais pas si toutes les ressources risquent de fuir ici, car endconnect () ne complète pas. Probablement rien le GC ne peut pas gérer. :)


Comment cela n'a-t-il pas été corrigé dans .NET 4.8?


4 Réponses :


0
votes

J'ai eu une erreur similaire et j'ai fini par utiliser ce code. Je ne sais pas si cela détiendra avec l'interface IAsyncResulte, mais il peut y avoir une manière similaire d'exécuter ce chèque. Je remarque que votre ar.asyncstate == null, alors essayez peut-être de commencer là-bas, c'est-à-dire qu'il est null lorsque vous vous connectez correctement?

private void OnConnect(IAsyncResult asyncResult)
{
    if (OnConnectCompleted == null) return; // Check whether something is using this wrapper
    AsyncCompletedEventArgs args;
    try
    {
        Socket outSocket = (Socket) asyncResult.AsyncState;

        // Complete connection
        outSocket.EndConnect(asyncResult);

        args = new AsyncCompletedEventArgs(null);
        OnConnectCompleted(this, args);
    }
    catch (Exception e)
    {
        args = new AsyncCompletedEventArgs(e.Message);
        OnConnectCompleted(this, args);
    }
}


2 commentaires

Asyncstate est utilisé pour transmettre certaines données personnalisées à la méthode de rappel. Je n'ai pas de tel besoin, c'est pourquoi c'est null. Il ne peut pas produire d'erreur. Je ne comprends pas votre exemple (c'est incomplet). IAsynCreulsulte n'a aucune erreur et je suppose que vous devriez fournir le code de la méthode de Closocket () car c'est votre propre méthode personnalisée. Autrement, je ne sais pas comment votre exemple de code pourrait être utile.


CloseSocket () déclenche simplement quelques événements pour notifier toute autre partie du programme, puis exécute () sur la prise.



1
votes

Le NullReferenceException code> est probablement dû à tcpclient.client code> étant null.

Si vous deviez suivre le EXEMPLE MSDN pour tcpclient.beginconnect code> et transmettez le tcpclient code> objet en tant que Objet d'état: p>

 private void onConnEst(IAsyncResult ar)
 {
      try
      {
           TcpClient client = (TcpClient)ar.AsyncState;
           if(client!=null && client.Client!=null)
           {
                client.EndConnect(ar);
           }
      }
      catch(Exception ex){...}
 }


6 commentaires

Pourquoi moulez-vous AR.ASYNCRESUT? Vouliez-vous dire ar.asyncstate? Quoi qu'il en soit, mon client est un membre privé, donc je n'ai pas besoin de le transmettre à la méthode ASYNC. Je suis actuellement incapable (c'est-à-dire pas au travail) de vérifier si le TCPClient.client est NULL. Toutefois, sur la base de ma mémoire et de ma précédente expérience, si je n'appelle pas client.EndConnect, l'application est toujours suspendue lorsque j'essaie de le fermer. Il dure généralement la même chose que le délai de connexion (~ 20). Et si je ne ferme pas l'application lors de la tentative de connexion, le BEGINCONNECT échouera après la même période.


Oups - vous êtes correct, ar.asycrélu devrait être ar.asyncstate . Post modifié pour refléter les changements.


Seriez-vous capable de publier la façon dont vous construisez le TCPCLIent et votre commenceur? Vous liez la prise avant de commencer? En outre, cela ne devrait pas y avoir d'importance, mais quel .NET Framework utilisez-vous?


J'ai mis à jour la question pour remplir les pièces manquantes. J'utilise .net 4.


Bien que je n'ai pas exécuté votre code exactement, Client.close () ne prend pas longtemps du tout. Je suggérerais de commenter les portions TCPClient de votre code (à des fins de test uniquement) et de voir si vous rencontrez toujours le retard. En dehors de cela, il pourrait y avoir quelque chose de poisson avec plusieurs threads verrouillant sur ConnectionAccess Causant le délai, ce qui serait logique si vous n'avez pas connu le retard lors de la progression du code.


J'ai déjà essayé de faire exclure tout code TCPClient, puis cela fonctionne très bien. Comme je l'ai dit, le temps qu'il faut pour que l'application se ferme correspond au temps nécessaire au début de l'échec de la FinConnexion après qu'aucune connexion n'a été faite (délai d'attente). Par conséquent, je conclus que c'est que l'async commencent le fil qui reste actif. À propos de l'impasse, ce n'est pas le problème, car ce sont les deux seuls endroits que la serrure est obtenue et à partir de ce que vous pouvez voir, fermer (dans un bloc de capture) n'est pas enfermé dans ce verrou.



1
votes

Ceci évidemment un bug à l'intérieur de la classe TCPClient. Je l'ai également fait face. Tcpclient.Dispose peut définir le champ client sur NULL, mais ne s'attend pas à cela.


1 commentaires

Bienvenue pour! Vous voudrez peut-être envisager d'élaborer un peu plus sur les détails de l'insecte pour rendre votre réponse un peu plus complète pour les autres personnes qui peuvent venir sur cette question.