给定下面的简单套接字客户端类,将其连接到 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
在收到零长度消息后立即停止呼叫,但这更像是一种练习。我想知道类似的错误是否可以保持在后台运行的持续回调流并窃取资源而不会发生明显的坏事。我必须承认我没有预料到这个特殊的例外。
问题1:为什么会这样?是否BeginXYZ
允许方法在同一个线程上立即执行回调?如果是这样,谁能说这在正常运行时不会发生?
问题 2:在这种情况下,有没有办法在保持“所需”行为的同时避免出现此异常?我的意思是触发不间断的回调流。
我正在使用带有 .NET 4 的 Visual Studio 2010。