Il codice seguente, nonostante apparentemente chiudendo il socket UDP, lascia appeso e incapace di ricollegare allo stesso indirizzo/porto.(Apparentemente) chiusa normalmente classe UdpClient lascia la presa bloccata
Queste sono le variabili di classe che uso:
Thread t_listener;
List<string> XSensAvailablePorts;
private volatile bool stopT_listener = false;
volatile UdpClient listener;
IPEndPoint groupEP;
ho creare e lanciare un nuovo thread con un metodo che gestirà la connessione socket e l'ascolto:
private void startSocketButton_Click(object sender, RoutedEventArgs e)
{
stopT_listener = false;
closeSocketButton.IsEnabled = true;
startSocketButton.IsEnabled = false;
t_listener = new Thread(UDPListener);
t_listener.Name = "UDPListenerThread";
t_listener.Start();
}
Il metodo è il seguente (Io uso un timeOut sulla Ricezione per non lasciarlo bloccato se non viene inviato nulla sulla presa e viene emesso uno Stop):
private void UDPListener()
{
int numberOfPorts = XSensAvailablePorts.Count();
int currAttempt = 0;
int currPort = 0;
bool successfullAttempt = false;
while (!successfullAttempt && currAttempt < numberOfPorts)
{
try
{
currPort = Int32.Parse(XSensAvailablePorts[currAttempt]);
listener = new UdpClient(currPort);
successfullAttempt = true;
}
catch (Exception e)
{
currAttempt++;
}
}
if (successfullAttempt)
{
//timeout = 2000 millis
listener.Client.SetSocketOption(SocketOptionLevel.Socket, SocketOptionName.ReceiveTimeout, 2000);
//Tried with and without, no change: listener.Client.SetSocketOption(SocketOptionLevel.Socket, SocketOptionName.ReuseAddress, true);
statusTB.Dispatcher.BeginInvoke((Action)delegate() { statusTB.Text = "Connected on port:" + currPort; });
groupEP = new IPEndPoint(IPAddress.Parse("143.225.85.130"), currPort);
byte[] receive_byte_array;
try
{
while (!stopT_listener)
{
try
{
receive_byte_array = listener.Receive(ref groupEP);
if (receive_byte_array.Length == 0 || receive_byte_array == null)
continue;
ParseData(receive_byte_array, samplingDatagramCounter);
}
catch (SocketException ex)
{
if (ex.SocketErrorCode == SocketError.TimedOut)
continue;
}
}
}
catch (Exception e)
{
Debug.Print(e.Message);
}
finally
{
if (listener != null)
{
listener.Client.Shutdown(SocketShutdown.Both);
listener.Close();
}
}
}
statusTB.Dispatcher.BeginInvoke((Action)delegate() { statusTB.Text = "Not Connected"; });
return;
}
posso ordinare il filo/presa per fermare con questo metodo:
private void closeSocketButton_Click(object sender, RoutedEventArgs e)
{
stopT_listener = true;
closeSocketButton.IsEnabled = false;
startSocketButton.IsEnabled = true;
t_listener.Join();
if (listener.Client != null)
{
listener.Client.Shutdown(SocketShutdown.Both);
listener.Close();
}
if (t_listener.IsAlive)
{
t_listener.Abort();
statusTB.Text = "Aborted";
}
else
statusTB.Text = "Not Connected";
}
Nonostante la registrazione di debug che la presa è stato chiuso, se riprovo collegare alla stessa porta, non sono in grado di farlo perché solleva un SocketException che dice che solo un uso di porta/indirizzo è normalmente permesso.
Potrebbe essere, che cosa 'listener.Client' è' null' quando si fa clic sul pulsante? Non chiamerai 'listener.Close()' allora. – Sinatr
@Sinatr Ho controllato il debug e non è il caso. –
. Chiudere() dovrebbe eliminare completamente l'oggetto. deve essere qualcos'altro, come non chiudere effettivamente il socket (probabilmente a causa di qualche eccezione non gestita e semplicemente ignorata). non so da quando ho appena usato il metodo .BeginReceive async per gestire i dati. ; p – porkchop