2015-11-16 6 views
0

Я пишу программное обеспечение, которое будет получать данные из UDP-пакета, а затем записывать его в файл. Это пример кода, который я написал как консольное приложение, чтобы проверить класс UdpClient.Будет ли переполнение буфера таймера во время ожидания приема UDP?

while(!done) 
{ 
Console.WriteLine("Receiving"); 
byte[] bytes = listener.Receive(ref groupEP); 
Console.WriteLine("Received"); 
} 

я узнал, что, если не было получено никаких UDP пакетов, в то время как цикл будет пауза в функции Receive (исх groupEP). Только тогда, когда будет получен пакет UDP, он перейдет к печати «Получено».

Однако для реальной программы (WPF), чтобы сохранить ресурсы, вместо этого я использую таймеры. В настоящее время он отлично работает для обновления интерфейса и файла, но мне было интересно, что произойдет, если таймер вызывается каждые 100 мс, тогда как UDP-пакеты принимаются только через 1 секунду (если я не знаю, когда я получу UDPs поэтому я выбираю 100 мс). Не будет ли это результатом 9 избыточных вызовов таймера каждые 1 секунду, и это приведет к переполнению? В настоящее время приложение отлично работает для этого scenerio, но я хотел бы понять, почему и если есть какие-либо возможные последствия.

ответ

0

Этот вопрос является пограничным «слишком широким». Вы подняли довольно много разных проблем. Тем не менее, пытаясь держать вещи короткими & hellip;

Как работает таймер, зависит от , который таймер вы фактически использовали. Если вы используете DispatcherTimer и вызывают Receive() от обработчика события таймера, то вы не получите избыточных событий таймера, потому что вместо этого вы будете блокировать поток пользовательского интерфейса. На самом деле это не очень хорошо, но, по крайней мере, это не приводит к слишком большому количеству событий таймера.

Если вы используете какой-либо другой таймер, то yes & hellip; выдача новой операции Receive() до того, как вы завершили предыдущий, приведет к увеличению числа незавершенных операций Receive(). Вы можете исправить это, поставив сокет в неблокирующий режим, но это откроет совершенно новую банку червей. Так и hellip;


На самом деле, вы не должны использовать метод блокировки Receive() вообще или таймер для любых целей, связанных с I/O. Вы должны использовать асинхронную версию ReceiveFrom(), например. BeginReceiveFrom(), который вы можете обернуть в Task.Factory.FromAsync(), чтобы вы могли использовать await вместо того, чтобы иметь дело с обратными вызовами. (Вы должны использовать ReceiveFrom(), чтобы вы могли фактически получить информацию о удаленной конечной точке для полученной дейтаграммы).

При использовании этого метода, вы будете цикл с await (при использовании FromAsync()) или вы будете называть BeginReceiveFrom() снова при обработке завершенной операции (если вы используете механизмы обратного вызова старого стиля). При этом вы можете одновременно активировать только одну операцию приема, но без блокировки какого-либо потока, и поэтому не нужно использовать таймер или другой механизм опроса сокета.

+0

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

+0

Извините, если мой ответ был недостаточно ясным. Я отредактирую его, чтобы попытаться его улучшить. Вы будете называть 'BeginReceiveFrom()' только один раз за датаграмму. После первого вызова вы ничего не делаете до тех пор, пока он не завершится, и вы обработали дейтаграмму. Затем вы вызываете это снова. Вы не будете использовать таймер вообще в этом подходе. –