Thread.Abort no parece arrojar una ThreadAbortException debido AcceptSocket
-
01-10-2019 - |
Pregunta
Estoy llamando ChannelServer.ListeningThread.Abort
en el siguiente hilo, sin embargo parece que nada sucede. Me gustaría ser más específicos, pero no puedo pensar en nada más. No parece haber ninguna ThreadAbortException
que se lanza, y esta excepción debe ser lanzado independientemente del oyente bloqueo (funciona perfectamente en las discusiones que se blockingly receptores).
EDITAR Importante : Con un ManualResetEvent.WaitOne
en lugar de AcceptSocket
, como Lyrik ha sugerido para la prueba, funciona perfectamente. ¿Cómo es que los bloques AcceptSocket
la ThreadAbortException
?
: Este hilo del foro parece hablar sobre el mismo tema, aunque no puedo descifrar nada de ella: http://www.tek-tips.com/viewthread.cfm?qid=319436&page=413
ChannelServer.ListeningThread = new Thread(new ThreadStart(delegate()
{
Log.Inform("Waiting for clients on thread {0}.", Thread.CurrentThread.ManagedThreadId);
while (true)
{
try
{
new Thread(new ParameterizedThreadStart(ChannelClientHandler.Initialize)).Start(ChannelServer.Listener.AcceptSocket());
}
catch (ThreadAbortException)
{
Log.Inform("Aborted client listening thread {0}.", Thread.CurrentThread.ManagedThreadId);
break;
}
}
}));
ChannelServer.ListeningThread.Start();
Solución 2
Esto funciona, pero es increíblemente descuidada e hilo-perder. Podría alguien me acaba de apuntar a una forma de lanzar una excepción que "AcceptSocket" no cogerá automáticamente?
ChannelServer.ListeningThread = new Thread(new ThreadStart(delegate()
{
Log.Inform("Waiting for clients on thread {0}.", Thread.CurrentThread.ManagedThreadId);
while (true)
{
try
{
ChannelServer.ClientConnected.Reset();
ChannelServer.Listener.BeginAcceptSocket(new AsyncCallback(ChannelClientHandler.EndAcceptSocket), ChannelServer.Listener);
ChannelServer.ClientConnected.WaitOne();
}
catch (ThreadInterruptedException)
{
Log.Inform("Interrupted client listening thread {0}.", Thread.CurrentThread.ManagedThreadId);
break;
}
}
}));
ChannelServer.ListeningThread.Start();
Otros consejos
No estoy seguro de por qué recibe ese error, pero aquí es un ejemplo simple que funciona:
ManualResetEvent mrse = new ManualResetEvent(false);
Thread test = new Thread(() =>
{
while (true)
{
try
{
mrse.WaitOne();
}
catch (ThreadAbortException)
{
Console.WriteLine("No problem here...");
}
}
});
test.IsBackground = true;
test.Start();
Thread.Sleep(1000);
test.Abort();
Console.ReadKey();
Así funciona para mí ... Asumí que ha caminado a través del depurador y su punto de ruptura dentro de la instrucción captura no fue alcanzado, ¿es correcto?
Nota:. Es mala práctica de Abort
llamada, en lugar usted debe llamar Interrupt
y manejar la ThreadInterruptedException
... es mucho más seguro
A continuación, un método de extensión AcceptSocket2
sencilla (lo siento por la falta de imaginación en relación con el nombre ...).
Funciona exactamente como el método AcceptSocket
originales.
using System;
using System.Net.Sockets;
using System.Threading;
/// <summary>
/// Extensions to TcpListener
/// </summary>
public static class TcpListenerExtensions
{
/// <summary>
/// Accepts a pending connection request.
/// </summary>
/// <param name="tcpListener">The TCP listener.</param>
/// <returns>
/// A <see cref="T:System.Net.Sockets.Socket" /> used to send and receive data.
/// </returns>
/// <exception cref="T:System.InvalidOperationException">The listener has not been started with a call to <see cref="M:System.Net.Sockets.TcpListener.Start" />.</exception>
/// <PermissionSet><IPermission class="System.Security.Permissions.EnvironmentPermission, mscorlib, Version=2.0.3600.0, Culture=neutral, PublicKeyToken=b77a5c561934e089" version="1" Unrestricted="true" /><IPermission class="System.Security.Permissions.FileIOPermission, mscorlib, Version=2.0.3600.0, Culture=neutral, PublicKeyToken=b77a5c561934e089" version="1" Unrestricted="true" /><IPermission class="System.Security.Permissions.SecurityPermission, mscorlib, Version=2.0.3600.0, Culture=neutral, PublicKeyToken=b77a5c561934e089" version="1" Flags="UnmanagedCode, ControlEvidence" /><IPermission class="System.Diagnostics.PerformanceCounterPermission, System, Version=2.0.3600.0, Culture=neutral, PublicKeyToken=b77a5c561934e089" version="1" Unrestricted="true" /></PermissionSet>
public static Socket AcceptSocket2(this TcpListener tcpListener)
{
Socket socket = null;
var clientConnected = new ManualResetEvent(false);
clientConnected.Reset();
tcpListener.BeginAcceptSocket(delegate(IAsyncResult asyncResult)
{
try
{
socket = tcpListener.EndAcceptSocket(asyncResult);
}
catch (ObjectDisposedException)
{ }
clientConnected.Set();
}, null);
clientConnected.WaitOne();
return socket;
}
}