以下の単純なソケット クライアント クラスを使用して、それを TCP サーバーに接続します (オンラインで無料で入手できる SocketTest3 を使用します)。次に、サーバーを切断して、少し待ちます。を取得する必要がありLockRecursionException
ます。
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Net;
using System.Net.Sockets;
using System.Threading;
namespace SocketRwlTest
{
public class SocketRwlTest
{
private Socket client = new Socket(AddressFamily.InterNetwork,
SocketType.Stream,
ProtocolType.Tcp);
private readonly ReaderWriterLockSlim rwl = new ReaderWriterLockSlim();
private const int maxLength = 200;
public SocketRwlTest(IPAddress address, ushort port)
{
client.Connect(new IPEndPoint(address, port));
ReceiveOne();
}
private void ReceiveOne()
{
rwl.EnterReadLock();
try
{
var inArray = new byte[maxLength];
client.BeginReceive(inArray, 0, maxLength, 0,
new AsyncCallback(ReceivedCallback),
inArray);
}
finally
{
rwl.ExitReadLock();
}
}
private void ReceivedCallback(IAsyncResult ar)
{
client.EndReceive(ar);
ReceiveOne();
}
}
}
与えられた単純化された例でなぜそれが起こるのか理解できません。ReceiveOne
長さ 0 のメッセージを受信したらすぐに通話を停止する必要があることはわかっていますが、これは練習問題です。同様のバグが、バックグラウンドで実行されているコールバックの一定のストリームを維持し、明らかに悪いことが起こることなくリソースを盗むことができるかどうか疑問に思いました. この特定の例外を予期していなかったことを認めなければなりません。
質問 1: なぜこれが起こるのですか? BeginXYZ
同じスレッドで、メソッドがコールバックを即座に実行できる可能性がありますか? もしそうなら、これが通常の実行時に起こり得ないと誰が言えるでしょうか?
質問 2: この場合、「望ましい」動作を維持しながら、この例外を回避する方法はありますか? つまり、コールバックのノンストップ ストリームを起動するということです。
.NET 4 で Visual Studio 2010 を使用しています。