Vb.net 在UDPClient异步回调期间,传入消息会发生什么情况?

Vb.net 在UDPClient异步回调期间,传入消息会发生什么情况?,vb.net,asynchronous,udpclient,Vb.net,Asynchronous,Udpclient,因此,每秒大约有30条UDP消息传入,我们正在对每条消息执行处理和数据库操作。我的第一个想法是完成操作,然后再次调用BeginReceive方法,让下一条消息进入。由于在收到消息和再次调用BeginReceive之间有一个微小的过渡,在这个过渡期间收到的消息会发生什么情况?另外,如果我在操作之前将BeginReceive移到异步回调的开头,这会导致各种线程复杂化,甚至可能安全地执行吗 Public Sub Start() _udpclient.BeginReceive(New Async

因此,每秒大约有30条UDP消息传入,我们正在对每条消息执行处理和数据库操作。我的第一个想法是完成操作,然后再次调用BeginReceive方法,让下一条消息进入。由于在收到消息和再次调用BeginReceive之间有一个微小的过渡,在这个过渡期间收到的消息会发生什么情况?另外,如果我在操作之前将BeginReceive移到异步回调的开头,这会导致各种线程复杂化,甚至可能安全地执行吗

Public Sub Start()
    _udpclient.BeginReceive(New AsyncCallback(AddressOf ReceiveCallback), Nothing)
End Sub
方法1:

Public Sub ReceiveCallback(ar As IAsyncResult)
    Try
        Dim bytes As Byte() = _udpclient.EndReceive(ar, _ipendpoint)
        HeavyProcessAndDBOperation(bytes)
        _udpclient.BeginReceive(New AsyncCallback(AddressOf ReceiveCallback), Nothing)
    Catch ex1 As Exception
    End Try
End Sub
方法2:

Public Sub ReceiveCallback(ar As IAsyncResult)
    Try
        Dim bytes As Byte() = _udpclient.EndReceive(ar, _ipendpoint)
        _udpclient.BeginReceive(New AsyncCallback(AddressOf ReceiveCallback), Nothing)
        HeavyProcessAndDBOperation(bytes)
    Catch ex1 As Exception
    End Try
End Sub

您希望客户端在收到数据包后尽快再次接收数据

如果我没记错的话,对
ReceiveCallback
的每次调用都将在一个单独的线程中触发,因此立即在回调中调用
BeginReceive
(按照方法2)就是您想要的模式

每个被触发的
ReceiveCallback
将有一个线程,也就是说:基本上是每个数据包。每个
ReceiveCallback
都会立即向
BeginReceive
触发一个线程,这将允许您接收尽可能多的数据

至于中间的数据包:请记住UDP是一种无连接协议。通过使用方法2,您将最小化但可能不会消除数据包丢失。您可能错过了
EndReceive
BeginReceive
之间的数据包

如果选择方法1,则会丢失
HeavyProcessAndDBOperation()
占用的时间窗口中发送的数据包数

ReceiveCallback
线程彼此独立,其中一个线程中处理的数据不会受到其他线程中处理的数据的影响,除非它是共享字段、数据库连接等。

在这里,您可能想做什么来修复共享字段等等,我不知道最好的解决方案,所以请恕我直言:在每个
ReceiveCallback
中触发另一个线程,进入
HeavyProcessAndDBOperation
。在该线程中,锁定实际的数据库操作和共享字段处理。这将增加处理数据所需的时间,但由于数据位于另一个线程中,因此不会影响其他数据包的接收操作

我不确定锁定处理块的正确方法。我曾经使用SyncLock,但我已经做了几年这种工作,所以你可能想在那里做一些研究


希望能有所帮助。

感谢您如此详细的回复,非常感谢!我正在考虑像下面这样解决它。。。共享字段读/写:同步锁,共享字段只读:无同步锁,共享数据库:多线程连接池。你觉得怎么样?读/写和只读对我来说很好,但是,正如我提到的,现在可能有更好的方法来实现这一点,因为已经有几年了。用谷歌快速搜索一下,看看你想要的是不是SyncLock。连接池也是有意义的,但是我对它没有太多的经验,也不能评论数据库端的潜在(如果有)死锁或其他共享访问问题。