Кажется, что Thread.Abort не генерирует исключение ThreadAbortException из-за AcceptSocket - PullRequest
3 голосов
/ 29 июня 2010

Я звоню ChannelServer.ListeningThread.Abort в следующей ветке, но, похоже, ничего не происходит. Я хотел бы быть более конкретным, но я не могу думать ни о чем другом. Кажется, что не генерируется ThreadAbortException, и это исключение следует генерировать независимо от блокирующего прослушивателя (он отлично работает на потоках, которые получают блокировку).

Важно РЕДАКТИРОВАТЬ : С ManualResetEvent.WaitOne вместо AcceptSocket, как предложил Лирик для тестирования, он работает отлично. Почему AcceptSocket блокирует ThreadAbortException?

ССЫЛКА : В этой теме форума обсуждается та же проблема, хотя я не могу ничего из нее выяснить: 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();

Ответы [ 3 ]

0 голосов
/ 29 июня 2010

Это работает, но это невероятно неряшливо и бесполезно.Может ли кто-нибудь просто указать мне способ создания исключения, которое «AcceptSocket» не будет автоматически перехватывать?

0 голосов
/ 28 марта 2014

Вот простой AcceptSocket2 метод расширения (извините за недостаток фантазии относительно названия ...). Он работает точно так же, как оригинальный метод AcceptSocket.

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;
    }
}
0 голосов
/ 29 июня 2010

Я не уверен, почему вы получаете эту ошибку, но вот простой пример, который работает:

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();

Так что это работает для меня ... Я предположил, что вы прошли черезотладчик и ваша точка останова внутри оператора catch не была достигнута, это правильно?

Примечание: плохая практика - вызывать Abort, вместо этого вы должны вызывать Interrupt и обрабатывать ThreadInterruptedException ..гораздо безопаснее.

...