0

我在一个令我困惑的应用程序中有一些奇怪的行为。

我创建了一个线程,我们称之为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 的线程和正在执行回调的线程的 ManagedThreadId,我发现有时它们具有相同的 ThreadId!

那可能吗?怎么会这样?关于我做错了什么的任何建议?

评论:实际代码并不完全一样,Transport 是 UDPClient 的包装器,它允许轻松更改传输层,锁不是真正的锁而是自旋锁......但概念本身或多或少是我写下来的.

4

1 回答 1

1

是一篇较早的文章,它讨论了 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);
于 2009-02-26T14:40:39.517 回答