Можно ли повторно использовать стандартный поток для пула потоков? - PullRequest
0 голосов
/ 26 февраля 2009

У меня странное поведение в приложении, которое меня озадачивает.

Я создаю поток, назовем его работником, который отвечает за обработку запросов на связь. Клиенты пишут в канал, в то время как поток принимает запросы и отправляет сообщения.

Теперь основной цикл потока выглядит примерно так:

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; может выполнить ...

Хорошо, сейчас .. проблема в том, что это не работает, ну, это работает время от времени ... почему? Если я отслеживаю ManagedThreadIds потоков, которые выполняют BeginSend, и того, который выполняет обратный вызов, я обнаруживаю, что иногда они имеют одинаковый ThreadId !!

Это возможно? Как это может случиться? Любые предложения о том, что я делаю не так?

Комментарий: фактический код не совсем такой, Transport - это оболочка для UDPClient, которая позволяет легко изменять транспортный уровень, блокировки на самом деле не блокировки, а спин-блокировки ... но сама концепция более или менее соответствует моей концепции. мы записали.

1 Ответ

1 голос
/ 26 февраля 2009

Здесь - более старая статья, в которой говорится о том, что функция Stream.BeginRead () фактически работает синхронно, а не асинхронно, как вы ожидаете. Статья написана в 2004 году, поэтому я предполагаю, что она ссылается на .NET 1.0 / 1.1. В статье специально не упоминается UdpClient.BeginSend (), но я часто спрашиваю себя, иногда ли функции BeginXXX в Socket работают одинаково, особенно если есть данные, которые нужно немедленно прочитать. Возможно, стоит проверить в Интернете, чтобы увидеть, если это возможно.

Можно ли передать client_id в функцию обратного вызова через параметр состояния функции BeginSend ()?

   object_id = Transport.BeginSend(xxx, xxx, Callback, client_id);
...