Thread.Abort non sembra gettare un ThreadAbortException a causa di AcceptSocket
-
01-10-2019 - |
Domanda
Chiedo ChannelServer.ListeningThread.Abort
su questo thread, ma nulla sembra accadere. Vorrei essere più precisi, ma non riesco a pensare a qualcosa di più. Non sembra esserci alcuna ThreadAbortException
che viene gettato, e questa eccezione dovrebbe essere gettato a prescindere di chi ascolta di blocco (che funziona perfettamente su discussioni che sono blockingly ricevitori).
Modifica Importante : Con un ManualResetEvent.WaitOne
invece di AcceptSocket
, come Lyrik ha suggerito per il test, funziona perfettamente. Come mai blocchi AcceptSocket
il ThreadAbortException
?
: questo thread del forum sembra per discutere lo stesso problema, anche se non posso figura nulla fuori di esso: 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();
Soluzione 2
Questo funziona, ma è incredibilmente sciatta e filo-spreco. Qualcuno potrebbe solo punto me un modo per generare un'eccezione che "AcceptSocket" non prenderà automaticamente?
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();
Altri suggerimenti
Non so perché che stai ricevendo questo errore, ma qui è un semplice esempio che le opere:
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();
Così funziona per me ... ho assunto hai fatto un passo attraverso il debugger e il vostro punto di rottura all'interno della istruzione catch non è stato colpito, è corretto?
. Nota: è cattiva pratica di chiamata Abort
, invece si dovrebbe chiamare Interrupt
e gestire il ThreadInterruptedException
... è molto più sicuro
Ecco un semplice metodo di estensione AcceptSocket2
(scusate per la mancanza di fantasia per quanto riguarda il nome ...).
Funziona esattamente come il metodo AcceptSocket
originale.
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;
}
}