Можно ли повторно использовать стандартный поток для пула потоков?

StackOverflow https://stackoverflow.com/questions/590657

Вопрос

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

Я создаю поток, назовем его 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; может казнить...

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

Возможно ли это?Как это могло произойти?Есть какие-нибудь предложения о том, что я делаю не так?

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

Это было полезно?

Решение

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

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

   object_id = Transport.BeginSend(xxx, xxx, Callback, client_id);
Лицензировано под: CC-BY-SA с атрибуция
Не связан с StackOverflow
scroll top