Según tengo entendido, Thread.Abort debe generar una ThreadAbortException en un hilo bloqueado, sin embargo, este no parece ser el caso cuando se trata de TcpListener.AcceptSocket
. Aquí está el ejemplo más básico de la cuestión:AcceptSocket no respeta un Thread.Abort request
class Program
{
static void Main(string[] args)
{
Thread thread = new Thread(Listen);
thread.Start();
Thread.Sleep(1000); // give it a second to get going
Console.WriteLine("Aborting listener thread");
thread.Abort();
thread.Join();
Console.WriteLine("Listener thread finished press <enter> to end app.");
Console.ReadLine();
}
static void Listen()
{
try
{
Console.WriteLine("Starting to listen");
TcpListener listener = new TcpListener(IPAddress.Any, 4070);
listener.Start();
Socket socket = listener.AcceptSocket();
Console.WriteLine("Connected!");
return;
}
catch (ThreadAbortException exception)
{
Console.WriteLine("Abort requested");
}
}
}
La llamada thread.Abort()
debe detener el AcceptSocket
y ejecutar el manejador ThreadAbortException
. Howerver esto no sucede.
Intercambio de mi Escuchar envoltorio de AcceptSocket
para ListenAsync que exige BeginAcceptSocket
lugar:
static void ListenAsync()
{
try
{
ManualResetEvent clientConnected = new ManualResetEvent(false);
Console.WriteLine("Starting to listen");
TcpListener listener = new TcpListener(IPAddress.Any, 4070);
listener.Start();
clientConnected.Reset();
var iasyncResult = listener.BeginAcceptSocket((ar) =>
{
Socket socket = listener.EndAcceptSocket(ar);
Console.WriteLine("Connected!");
clientConnected.Set();
}, null);
clientConnected.WaitOne();
return;
}
catch (ThreadAbortException exception)
{
Console.WriteLine("Abort requested");
}
}
En este caso "parece" que funcione bien. ThreadAbortException se detecta mientras el hilo está haciendo un WaitOne. Sin embargo, el hilo que fue creado por la llamada a BeginAcceptSocket todavía se está ejecutando y capaz de aceptar una toma (I verificado esto mediante la apertura de dicho puerto con Telnet)
Finalmente, añadí Listener.Stop
como parte del controlador de TheadAbortException
, y una oportunidad atrapar alrededor de la llamada EndAcceptSocket (ya que el socket está dispuesto por el Stop)
¿Es este realmente el mejor enfoque para iniciar y detener el proceso de escuchar conexiones de socket?
¿Qué sucede con el evento clientConnected cuando mata el hilo? ¿Por qué no te deshaces de los objetos? ¿Qué haces con el socket una vez aceptado? –
El uso de 'Thread.Abort' es casi siempre un hack sucio y debe evitarse. Deje que sus hilos terminen con elegancia ... no tire de la alfombra debajo de ellos. – spender