我在一个令我困惑的应用程序中有一些奇怪的行为。
我创建了一个线程,让我们称之为worker,它负责处理通信请求。当线程消耗请求并发送消息时,客户端在管道上写入。
现在,线程的主循环有这样的东西:
lock(this)
{
object_id = Transport.BeginSend(xxx, xxx, callback, yyy)
clientsObjects[object_id] = client_id;
}
现在回调需要访问client_id(它比我写的要复杂一点,但问题是回调接收到object_id,只是假设BeginSend是对UdpClient.BeginSend
的调用
void Callback(IAsyncResult ar)
{
State st = (State)ar;
lock(this)
{
client_id = clientsObjects[st.object_id]
}
}
锁是存在的,因为回调可能会如此快速地发生,以至于clientsObjects[object_id] = client_id;
可以执行之前实际发生...
好的,现在..问题是它不起作用,它现在有效吗......为什么?如果我跟踪正在执行BeginSend的线程的ManagedThreadIds和正在执行回调的线程,我发现有时它们具有相同的ThreadId !!
这可能吗?怎么会发生这种情况?关于我做错了什么的任何建议?
评论:实际代码并不完全相同,Transport是UDPClient的包装器,允许轻松更改传输层,锁不是真正的锁而是自旋锁...但概念本身或多或少是我的'写下来。
答案 0 :(得分:1)
Here是一篇较旧的文章,它讲述了实际同步操作的Stream.BeginRead()函数,而不是像你期望的那样异步。这篇文章是从2004年开始的,所以我假设它指的是.NET 1.0 / 1.1。本文没有具体引用UdpClient.BeginSend(),但我经常想知道Socket中的BeginXXX函数是否有时会有相同的行为,特别是如果有数据要立即读取的话。可能值得检查网络,看看是否有可能。
是否可以通过BeginSend()函数的state参数将client_id传递给回调函数?
object_id = Transport.BeginSend(xxx, xxx, Callback, client_id);