是否可以为线程池重用标准线程?

时间:2009-02-26 14:00:04

标签: c# .net multithreading asynchronous threadpool

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

我创建了一个线程,让我们称之为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的包装器,允许轻松更改传输层,锁不是真正的锁而是自旋锁...但概念本身或多或少是我的'写下来。

1 个答案:

答案 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);