0

我正在编写一个软件,它将从 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 个冗余计时器调用,这会导致溢出吗?目前该应用程序在这个场景中运行良好,但我想了解为什么以及是否有任何可能的后果。

4

1 回答 1

0

这个问题是“太宽泛”的边界。你提出了很多不同的问题。也就是说,试图保持简短......

计时器的行为取决于您实际使用的计时器如果您正在使用DispatcherTimer并且正在从计时器事件处理程序调用Receive(),那么您将不会获得多余的计时器事件,因为您将阻塞 UI 线程。这实际上一点都不好,但至少它不会导致获得太多的计时器事件。

如果您使用的是其他类型的计时器,那么是的……在完成前一个操作之前发出新Receive()操作将导致未完成Receive()操作的数量不断增加。您可以通过将套接字置于非阻塞模式来解决此问题,但这会打开一个全新的蠕虫罐。所以…


事实上,您根本不应该使用阻塞Receive()方法,也不应该将计时器用于任何与 I/O 相关的目的。您应该使用 的异步版本ReceiveFrom(),例如BeginReceiveFrom(),您可以将其包装在 a 中Task.Factory.FromAsync(),以便您可以使用await而不是处理回调。(您应该使用ReceiveFrom(),以便您可以实际获取您收到的数据报的远程端点信息)。

使用此技术时,您将循环使用await(如果使用FromAsync()),或者BeginReceiveFrom()在处理完成的操作时再次调用(如果您使用旧式回调机制)。这样,您一次只能激活一个接收操作,但根本不会阻塞任何线程,因此无需使用计时器或其他机制来轮询套接字。

于 2015-11-16T01:49:36.693 回答