thread.abortは、AcceptSocketのためにthreadabortexceptionをスローしていないようです
-
01-10-2019 - |
質問
呼んでいます ChannelServer.ListeningThread.Abort
次のスレッドでは、何も起こらないようです。もっと具体的になりたいのですが、これ以上何も考えられません。ノーはないようです ThreadAbortException
それはスローされており、この例外はブロッキングリスナーに関係なくスローする必要があります(ブロッキングすることをレシーブしているスレッドで完全に機能します)。
重要な編集: : とともに ManualResetEvent.WaitOne
それ以外の AcceptSocket
, 、Lyrikがテストのために提案しているように、それは完全に機能します。どうして 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();
解決 2
これは機能しますが、信じられないほどずさんで糸を磨くことです。誰もが私を「受け入れる」ことを自動的にキャッチしないという例外を投げる方法を教えてもらえますか?
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();
他のヒント
なぜそのエラーが発生しているのかわかりませんが、ここに機能する簡単な例があります。
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();
だからそれは私のために働いています...私はあなたがデバッガーを踏んだと思いました、そして、キャッチステートメント内のあなたのブレークポイントはヒットしませんでした、それは正しいですか?
注:電話するのは悪い習慣です Abort
, 、代わりに電話する必要があります Interrupt
そして、を処理します ThreadInterruptedException
...それははるかに安全です。
ここにシンプル 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;
}
}