Resizing form with anchored image (from MemoryStre

2020-05-03 01:10发布

问题:

I have a TcpListener which gets an endless stream of byte array. From that, I convert the byte() to MemoryStream and feed a PictureBox to display the images. That works fine. If I set the anchor points on the PictureBox to top/right/bottom/left which means the image will expand when the form expands and then I actually expand the form, I get the following error:

An unhandled exception of type 'System.ArgumentException' occurred in System.Drawing.dll

Additional information: Parameter is not valid.

Also,

The application is in break mode

Code

 ' Enter the listening loop.
        While True
            Dim client As TcpClient = Await server.AcceptTcpClientAsync()
            Dim stream As NetworkStream = client.GetStream
            Dim MS As New MemoryStream
            Await stream.CopyToAsync(MS)
            Await ViewImage(MS)
            client.Close()
        End While

View image function:

   Public Async Function ViewImage(ms As MemoryStream) As Task
        Try
            Dim myimage As Bitmap
            myimage = New Bitmap(ms)
            PictureBox1.Image = myimage
            PictureBox1.Refresh()
            myimage.Dispose()
        Catch ex As Exception
            MessageBox.Show(ex.ToString)
        End Try

    End Function

Please note that the exception is not caught within my code. Any ideas?

回答1:

The issue is most likely related to the fact that you dispose myimage at the end of your ViewImage() method.

This:

PictureBox1.Image = myimage
...
myimage.Dispose()

makes myimage and PictureBox1.Image point to the same Bitmap object. Bitmaps are reference types (classes) which means that you're just passing their reference pointer around when you assign it to different variables.

Thus when you dispose myimage you are disposing the same image that is being shown in the PictureBox, which could cause that error of yours when GDI+ tries to redraw a stretched version of it (as a matter of fact not even the original image should be displayed once you've disposed it).

For more info see: Value Types and Reference Types - Microsoft Docs.


Basic example of how Reference Types and Value Types work

Reference types:

Dim A As New Bitmap("image.bmp")

Dim B As Bitmap = A 'Points to A.
PictureBox1.Image = A 'Points to A.
PictureBox2.Image = B 'Still points to A.

'Calling Dispose() on any of the above will result in none of them having an image since you will ultimately dispose bitmap A.

Value types:

Dim A As Integer = 3

Dim B As Integer = A 'Copy of A.
Dim C As Integer = B 'Copy of B.

C = 4 'Results in A = 3, B = 3, C = 4.