1

我使用下面的代码的目的是在我的表单打开时开始(异步)查找 UDP 数据报。当收到数据报时,我想做的就是调用一个在主线程上运行的过程(传递接收到的消息),然后重新开始寻找另一个数据报。假设代码在数据报显示之前是正确的,我该如何执行接下来的两个步骤?我真的对跨线程操作、委托等感到困惑。谢谢。另外,我想继续使用 .Net 4.0。

Const RcvPort As Integer = 33900
Public RRWEndPoint As IPEndPoint = New IPEndPoint(myIPaddr, RcvPort)
Public SiteEndPoint As IPEndPoint = New IPEndPoint(IPAddress.Any, RcvPort)
Public dgClient As UdpClient = New UdpClient(RRWEndPoint)

Private Sub Form1_Load(sender As Object, e As System.EventArgs) Handles Me.Load
    dgClient.BeginReceive(AddressOf UDPRecv, Nothing)
End Sub

Public Sub UDPRecv(ar As IAsyncResult)
    Dim recvBytes As Byte() = dgClient.EndReceive(ar, SiteEndPoint)
    Dim recvMsg As String = Encoding.UTF8.GetString(recvBytes)

    dgClient.BeginReceive(AddressOf UDPRecv, Nothing)
End Sub
4

1 回答 1

4

您的 UDPRecv() 方法将在 I/O 完成线程上运行。任何从该线程更新 UI 的尝试都会炸毁您的程序。您必须使用表单的 BeginInvoke() 方法将字符串传递给在 UI 线程上运行的方法。您还必须处理程序终止时关闭的套接字,这需要捕获 EndReceive() 调用将抛出的 ObjectDisposedException。

所以让它看起来像这样:

Public Sub UDPRecv(ar As IAsyncResult)
    Try
        '' Next statement will throw when the socket was closed
        Dim recvBytes As Byte() = dgClient.EndReceive(ar, SiteEndPoint)
        Dim recvMsg As String = Encoding.UTF8.GetString(recvBytes)
        '' Pass the string to a method that runs on the UI thread
        Me.BeginInvoke(New Action(Of String)(AddressOf DataReceived), recvMsg)
        '' Continue receiving
        dgClient.BeginReceive(AddressOf UDPRecv, Nothing)
    Catch ex As ObjectDisposedException
        '' Socket was closed, do nothing
    End Try
End Sub

Private Sub DataReceived(recvMsg As String)
    '' This method runs on the UI thread
    '' etc...
End Sub

Private Sub Form1_FormClosing(sender As Object, e As FormClosingEventArgs) Handles MyBase.FormClosing
    '' Close the socket when the form is closed
    dgClient.Close()
End Sub
于 2013-09-01T13:58:43.803 回答