Позволяя клиенту извлекать данные - PullRequest
1 голос
/ 11 июля 2009

Я пишу сервер на C #, который создает (длинный, возможно, даже бесконечный) IEnumerable<Result> в ответ на запрос клиента, а затем передает эти результаты обратно клиенту.

Могу ли я установить его так, чтобы, если клиент читает медленно (или, возможно, вообще не читает пару секунд за раз), серверу не понадобится остановленный поток, ожидающий очистки пространства буфера что он может получить следующую пару Result s, сериализовать их и вставить их в сеть?

Так работает NetworkStream.BeginWrite? Документация неясна (для меня) о том, когда будет вызываться метод обратного вызова. Происходит ли это в основном немедленно, просто в другом потоке, который затем блокирует EndWrite в ожидании фактической записи? Происходит ли это, когда какой-то низкоуровневый буфер в сокетах API проигрывает? Это происходит, когда данные фактически записаны в сеть? Это происходит, когда это было подтверждено?

Я в замешательстве, поэтому есть вероятность, что весь этот вопрос за пределами базы. Если да, не могли бы вы повернуть меня и указать правильное направление, чтобы решить то, что, как я ожидал, является довольно распространенной проблемой?

Ответы [ 2 ]

2 голосов
/ 11 июля 2009

Я отвечу на третью часть вашего вопроса более подробно.

Документация MSDN гласит:

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

Насколько я понимаю, будет ли метод обратного вызова вызываться сразу после вызова BeginSend, зависит от базовой реализации и платформы. Например, если порты завершения ввода-вывода доступны в Windows, этого не будет. Поток из пула потоков будет заблокирован перед вызовом.

Фактически, метод BeginWrite от NetworkStream просто вызывает метод BeginSend базового сокета в моей реализации .Net. Мой использует основную функцию WSASend Winsock с портами завершения, где это возможно. Это делает его гораздо более эффективным, чем просто создание собственного потока для каждой операции отправки / записи, даже если вы должны использовать пул потоков.

Затем метод Socket.BeginSend вызывает метод OverlappedAsyncResult.CheckAsyncCallOverlappedResult, если результатом WSASend был IOPending, который, в свою очередь, вызывает собственную RegisterWaitForSingleObject функцию Win32. Это приведет к тому, что один из потоков в пуле потоков будет блокироваться до тех пор, пока метод WSASend не сообщит о своем завершении, после чего вызывается метод обратного вызова.

Метод Socket.EndSend, вызываемый NetworkStream.EndSend, будет ожидать завершения операции отправки. Причина этого заключается в том, что если порты завершения ввода-вывода недоступны, метод обратного вызова будет вызван сразу.

Я должен еще раз подчеркнуть, что эти детали относятся к моей реализации .Net и моей платформы, но, надеюсь, это даст вам некоторое представление.

0 голосов
/ 11 июля 2009

Во-первых, единственный способ продолжить выполнение основного потока, пока выполняется другая работа, - использовать другой поток. Нить не может делать две вещи одновременно.

Тем не менее, я думаю, что вы пытаетесь избежать беспорядка с объектом Thread, и да, это возможно благодаря использованию BeginWrite. По вашим вопросам

Документация неясна (для меня) о том, когда метод обратного вызова будет называется.

Вызов выполняется после того, как сетевой драйвер считывает данные в свои буферы.

Это происходит в основном сразу, просто в другой теме, которая затем блоки на EndWrite в ожидании фактическое письмо произойдет?

Нет, только пока он не будет в буферах, обрабатываемых сетевым драйвером.

Это происходит, когда какой-то буфер нижнего уровня в сокетах API недорасход

Если из-за недостатка в вашем средстве есть место для этого, тогда да.

Это происходит, когда данные были на самом деле записывается в сеть?

номер

Это происходит, когда это было признал?

номер

EDIT

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

...