gpt4 book ai didi

c# - ReaderWriterLockSlim 使用 Socket.BeginReceive 引发 LockRecursionException

转载 作者:行者123 更新时间:2023-12-03 12:04:29 25 4
gpt4 key购买 nike

给定下面的简单套接字客户端类,将其连接到 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一旦我收到一条长度为零的消息,但这更像是一种练习。我想知道类似的错误是否可以保持在后台运行的持续回调流并窃取资源而不会发生明显的坏事。我必须承认我没有预料到这个特殊的异常(exception)。

问题1:为什么会这样?是 BeginXYZ方法可能允许在同一个线程上立即执行回调?如果是这样,谁能说这在正常运行时不会发生?

问题 2:在这种情况下,有没有办法在保持“所需”行为的同时避免出现此异常?我的意思是触发不间断的回调流。

我正在使用带有 .NET 4 的 Visual Studio 2010。

最佳答案

Question 1: Why does this happen? Are BeginXYZ methods perhaps allowed to execute callbacks instantly, on the same thread? If that's the case, who's to say this couldn't happen during normal runtime?



如所述 by mike z in the comments , BeginReceive()方法不需要异步执行。如果数据可用,它将同步执行,在同一个线程中调用回调委托(delegate)。根据定义,这是一个递归调用,因此与使用非递归锁对象(例如您在此处使用的 ReaderWriterLockSlim)不兼容。

这当然可以“在正常运行时”发生。我不确定我是否理解你问题的第二部分。谁说这不可能发生?没有人。这有可能发生。

Question 2: Are there ways to avoid getting this exception while still maintaining the "desired" behaviour in this case? I mean fire a non-stopping stream of callbacks.



恐怕我也不知道“触发不间断的回调流”是什么意思。

一种明显的解决方法是在 ReaderWriterLockSlim 上启用递归。对象通过 LockRecursionPolicy.SupportsRecursion到它的构造函数。或者,您可以查看 IsReadLockHeld试图拿锁之前的属性(property)。

从您的代码示例中不清楚为什么您有锁,更不用说为什么以这种特定方式使用它。正确的解决方案可能是在您调用 BeginReceive() 时根本不持有锁。 .仅在处理 EndReceive() 的结果时使用.

关于c# - ReaderWriterLockSlim 使用 Socket.BeginReceive 引发 LockRecursionException,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/34931124/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com