等待 UDP 接收时我的计时器缓冲区会溢出吗?
Posted
技术标签:
【中文标题】等待 UDP 接收时我的计时器缓冲区会溢出吗?【英文标题】:Will my timer buffer overflow while waiting for UDP receive? 【发布时间】:2016-02-17 01:46:37 【问题描述】:我正在编写一个软件,它将接收来自 UDP 数据包的数据,然后将其写入文件。这是我作为控制台应用程序编写的示例代码,用于测试 UdpClient 类。
while(!done)
Console.WriteLine("Receiving");
byte[] bytes = listener.Receive(ref groupEP);
Console.WriteLine("Received");
我发现如果没有收到 UDP 数据包,while 循环将在 Receive(ref groupEP) 函数处暂停。只有在收到 UDP 数据包时,才会继续打印“已接收”。
但是对于实际程序(WPF),为了节省资源,我使用了计时器。目前更新接口和文件工作正常,但我一直想知道如果每 100 毫秒调用一次计时器会发生什么,而 UDP 数据包仅每 1 秒接收一次(假设我不知道什么时候会收到 UDP所以我选择100ms)。 这不会导致每 1 秒有 9 个冗余计时器调用,这会导致溢出吗?目前该应用程序在这个场景中运行良好,但我想了解为什么以及是否有任何可能的后果。
【问题讨论】:
【参考方案1】:这个问题“太宽泛”了。你提出了很多不同的问题。也就是说,尽量保持简短……
计时器的行为取决于您实际使用的哪个计时器。如果您正在使用DispatcherTimer
并从计时器事件处理程序调用Receive()
,那么您将不会获得多余的计时器事件,因为您将阻塞 UI 线程。这实际上一点都不好,但至少不会导致获得太多计时器事件。
如果您使用的是其他类型的计时器,那么是的……在完成前一个操作之前发出新的Receive()
操作将导致未完成的Receive()
操作数量不断增加。您可以通过将套接字置于非阻塞模式来解决此问题,但这会打开一个全新的蠕虫罐。所以……
事实上,您根本不应该使用阻塞 Receive()
方法,也不应该使用任何与 I/O 相关的计时器。您应该使用 ReceiveFrom()
的异步版本,例如BeginReceiveFrom()
,您可以将其包装在 Task.Factory.FromAsync()
中,以便您可以使用 await
而不是处理回调。 (您应该使用ReceiveFrom()
,这样您才能真正获取您收到的数据报的远程端点信息)。
使用此技术时,您将循环使用await
(如果使用FromAsync()
),或者在处理完成的操作时再次调用BeginReceiveFrom()
(如果您使用旧式回调机制)。这样,您一次只能激活一个接收操作,而不会阻塞任何线程,因此无需使用计时器或其他机制来轮询套接字。
【讨论】:
如果我一直调用ReceiveFrom()会不会一样,只是我一直通过我的定时器调用函数生成异步线程? 对不起,如果我的回答不够清楚。我将对其进行编辑以尝试改进它。每个数据报只能调用一次BeginReceiveFrom()
。在第一次调用之后,你什么都不做,直到它完成并且你已经处理了数据报。然后你再次调用它。在这种方法中,您根本不会使用计时器。以上是关于等待 UDP 接收时我的计时器缓冲区会溢出吗?的主要内容,如果未能解决你的问题,请参考以下文章