You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

运行时在PictureBox中显示UDP接收图片失败问题求助

问题:UDP接收的图片无法在PictureBox显示,但存盘可正常打开

我通过UDP从其他主机持续接收图片字节,尝试在运行时显示在PictureBox控件中,但所有图片都无法正常显示。不过把接收的字节保存到磁盘后,图片能正常打开。

我的实现代码如下:

Sub ReceiveImageContinuously()
    Dim udpClient As New UdpClient(11000)
    Console.WriteLine($"Listening for UDP packets on port {11000}...")

    Try
        While True
            Dim receivedBytes As New List(Of Byte)()

            While True
                ' Receive a packet
                Dim remoteEndPoint As New IPEndPoint(IPAddress.Any, 0)
                Dim receivedChunk As Byte() = udpClient.Receive(remoteEndPoint)
                Dim receivedMessage As String = System.Text.Encoding.UTF8.GetString(receivedChunk)

                ' Check for termination signal
                If receivedMessage = "END" Then
                    Console.WriteLine("Received image file termination signal.")
                    Exit While
                End If

                ' Add received chunk to the list
                receivedBytes.AddRange(receivedChunk)
                Console.WriteLine($"Received chunk of size {receivedChunk.Length}")
            End While

            ' Combine all chunks into a single byte array
            Dim completeImageBytes As Byte() = receivedBytes.ToArray()

            LoadPictureBox(completeImageBytes)
            
        End While
    Catch ex As Exception
        Console.WriteLine($"Error: {ex.Message}")
    Finally
        udpClient.Close()
    End Try
End Sub

Public Sub LoadPictureBox(receivedBytes As Byte())
    Try
        ' Validate the received bytes
        If receivedBytes Is Nothing OrElse receivedBytes.Length = 0 Then
            Console.WriteLine("Received an empty byte array.")
            Return
        End If

        ' Use MemoryStream to create an Image from byte array
        Using ims As New MemoryStream(receivedBytes)
            ' Attempt to load the image
            Dim img As Image = Image.FromStream(ims)

            ' Check if Invoke is required
            If PictureBox1.InvokeRequired Then
                PictureBox1.Invoke(Sub()
                                       PictureBox1.Image = img
                                       PictureBox1.Refresh()
                                   End Sub)
            Else
                PictureBox1.Image = img
                PictureBox1.Refresh()
            End If
        End Using

    Catch ex As Exception
        ' Log or display error message for debugging
        Console.WriteLine($"Error loading image: {ex.Message}")
        MessageBox.Show($"Error loading image: {ex.Message}", "Error", MessageBoxButtons.OK, MessageBoxIcon.Error)
    End Try
End Sub

我用以下代码保存图片到磁盘,保存后的图片可正常打开:

Dim savePath As String = Path.Combine(saveFolderPath, $"received_image_{cycle}.jpg")
File.WriteAllBytes(savePath , completeImageBytes)

问题原因及解决方法

  1. 核心问题:流生命周期冲突
    LoadPictureBox方法中,MemoryStream被包裹在Using语句中,代码离开Using块时流会自动关闭。但Image.FromStream要求流在图像的整个生命周期内保持打开状态,流关闭后图像无法正常渲染,这就是存盘正常但控件显示失败的原因。

  2. 修改后的LoadPictureBox方法

Public Sub LoadPictureBox(receivedBytes As Byte())
    Try
        If receivedBytes Is Nothing OrElse receivedBytes.Length = 0 Then
            Console.WriteLine("Received an empty byte array.")
            Return
        End If

        Dim ims As New MemoryStream(receivedBytes)
        Dim img As Image = Image.FromStream(ims)
        ' 克隆图像,脱离对原流的依赖
        Dim clonedImg As Image = DirectCast(img.Clone(), Image)

        If PictureBox1.InvokeRequired Then
            PictureBox1.Invoke(Sub()
                                   ' 释放旧图像资源,避免内存泄漏
                                   If PictureBox1.Image IsNot Nothing Then
                                       PictureBox1.Image.Dispose()
                                   End If
                                   PictureBox1.Image = clonedImg
                                   PictureBox1.Refresh()
                               End Sub)
        Else
            If PictureBox1.Image IsNot Nothing Then
                PictureBox1.Image.Dispose()
            End If
            PictureBox1.Image = clonedImg
            PictureBox1.Refresh()
        End If

        ' 手动释放流和原始图像资源
        ims.Dispose()
        img.Dispose()

    Catch ex As Exception
        Console.WriteLine($"Error loading image: {ex.Message}")
        MessageBox.Show($"Error loading image: {ex.Message}", "Error", MessageBoxButtons.OK, MessageBoxIcon.Error)
    End Try
End Sub
  1. 额外注意事项
  • 每次更新PictureBox的Image时,必须释放旧图像的资源,防止内存泄漏。
  • 当前代码未处理UDP数据包乱序问题,若发送端分包时未保证顺序,后续可能出现图像拼接错误(目前存盘正常说明顺序无问题,可根据实际场景补充顺序校验逻辑)。

内容的提问来源于stack exchange,提问作者Tanmay Chakraborty

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.06.15 03:14:59