2010-03-02 5 views
0

J'ai une classe qui hérite de TcpListener, cette classe Shadows la méthode Start juste pour appeler la base Start() et la base BeginAcceptTcpClient(). De temps en temps, la méthode est appelée mais le port n'est pas ouvert (netstat n'affiche pas le port ouvert).TcpListener.Start() n'ouvre pas le port

La classe ressemble à ceci

Public Class ExtendedTcpListener 
    Inherits System.Net.Sockets.TcpListener 

Public Shadows Sub Start() 
    SyncLock (m_stopLock) 
     MyBase.Start() 
     MyBase.BeginAcceptTcpClient(AddressOf Me.CompleteAcceptTcpClient, Me) 
     My.Application.Log.WriteEntry("Extended Tcp Listener started ...", TraceEventType.Verbose) 
    End SyncLock 
End Sub 

Toute idée sur ce qui se passe ou comment déboguer le problème? Comme le Start() est appelé sans exception je m'attendais à trouver le port toujours ouvert (le journal est toujours écrit).

Informations supplémentaires: lorsque la méthode Start fonctionne correctement, elle fonctionne à chaque fois jusqu'à ce que l'application soit redémarrée. Lorsque la méthode Start ne fonctionne pas, elle ne fonctionnera plus tant que l'application ne sera pas redémarrée.

Edit: Il y a aussi une méthode d'arrêt au ExtendedTcpListener:

Public Shadows Sub [Stop]() 
    SyncLock (m_stopLock) 
     MyBase.Stop() 
     My.Application.Log.WriteEntry("... extended Tcp Listener stopped", TraceEventType.Verbose) 
    End SyncLock 
End Sub 

La classe qui utilise le ExtendedTcpListener implémente le modèle IDisposable et à l'intérieur du Éliminez le ExtendedTcpListener.Stop est appelé.

Le texte d'arrêt n'est pas présent dans les journaux lorsque les problèmes se produisent.

Répondre

0

Se pourrait-il que, après la première fois que Start est appelé, une autre méthode/thread obtienne un verrou sur m_stopLock? (quel type d'objet est m_stopLock?)

Pouvez-vous regarder avec le débogueur et voir si le constructeur d'observation est appelé? (ou définir une trace avant SynchLock)

+0

Non. Au fur et à mesure que la chaîne "Extended Tcp Listener started ..." est écrite, le verrou n'est pas pris à l'arrivée. Le m_stopLock est un objet utilisé principalement comme verrou de démarrage et d'arrêt, pour éviter le démarrage et l'arrêt en même temps. –

+0

Que voulez-vous dire par "Pouvez-vous regarder avec le débogueur et voir si le constructeur de l'observation est appelé?". Le constructeur de base est toujours appelé parce que mon seul constructeur appelle Mybase.New() –

+0

Pour que je comprenne: le problème n'est pas que du code ne soit pas exécuté (MyBase.BeginAcceptTcpClient (AddressOf Me.CompleteAcceptTcpClient, Me)), ce que je pensais - mais que bien que le code soit exécuté, le port n'est toujours pas ouvert. Est-ce correct? – Ando

0

Ne disposez-vous pas de l'objet trop tôt? Pouvons-nous voir le code dans lequel vous créez une instance de ExtendedTcpListener et comment vous le gérez?

+0

Il serait très rare car il est utilisé uniquement par une autre classe qui implémente IDisposable et cette classe appelle la méthode ExtendedTcpListener Stop qui a un autre journal qui écrit "Extended Tcp Listener Stopped ..." (ce texte n'est bien sûr pas présent lorsque le problème arrive). Quoi qu'il en soit, je vais mettre le code comme un edit. –

0

C'est un drôle, d'accord. Si je comprends bien, une fois que le problème commence à se produire, vous pouvez le reproduire facilement, non? Si c'est le cas, j'attacherais le débogueur à ce point et inspecterais l'objet TcpListener et son Socket sous-jacent (m_ServerSocket). Il n'y a pas d'instructions précises que je puisse donner ici, il suffit de regarder et de voir si quelque chose semble être hors de propos ou tout simplement différent de la façon dont les choses fonctionnent.

0

Il me semble très dangereux que vous héritiez de TcpListener et de remplacer une méthode non virtuelle en utilisant Shadows. Avez-vous essayé de changer votre code pour ne pas hériter de TcpListener, mais simplement l'encapsuler?

Edit: ajouté exemple de code

Public Class ExtendedTcpListener 
    ' Inherits System.Net.Sockets.TcpListener <== DO NOT INHERIT 

    Private MyTcpListener As New TcpListener() 

    Public Sub Start() 
    SyncLock (m_stopLock) 
     MyTcpListener.Start() 
     MyTcpListener.BeginAcceptTcpClient(AddressOf Me.CompleteAcceptTcpClient, Me) 
     My.Application.Log.WriteEntry("Extended Tcp Listener started ...", TraceEventType.Verbose) 
    End SyncLock 
    End Sub 

    ' ... 
End Class 
+0

Pourquoi est-ce dangereux? Les ombres sont destinées à être utilisées de cette manière n'est-ce pas? –

+0

Les ombres sont comme "forcer" un remplacement d'une méthode non virtuelle (non héritable). Cela casse le polymorphisme: si vous passez votre ExtendedTcpListener à une méthode qui attend un TcpListener (ou simplement l'assigner à une variable TcpListener déclarée), la méthode Start et Stop de la classe TcpListener sera appelée à la place de votre override. Les "ombres" sont mauvaises, évitez-les comme l'enfer - essayez d'encapsuler au lieu d'hériter de cette façon. –

+0

Ok, je vois le point, de toute façon ce n'est pas le problème ici car la classe est toujours utilisée comme ExtendedTcpListener et n'est utilisée qu'une seule fois. Merci quand même. –