简体   繁体   中英

c# Drawing bitmap over another one

I'm working on a project,and i need to draw blocks of images(as bitmaps) which i receive from a socket on an already existing image (which i define in the beggining of the program),and to display it on a PictureBox -in other words,to update the image everytime i receive a new block.

In order to do this asynchronously, i use a Thread which read the data from the Socket and process it.

This is my code:

private void MainScreenThread() {

ReadData();
initial = bufferToJpeg(); //full screen first shot.
pictureBox1.Image = initial;

while (true) {
 int pos = ReadData();
 int x = BlockX();
 int y = BlockY();
 Bitmap block = bufferToJpeg(); //retrieveing the new block.

 Graphics g = Graphics.FromImage(initial);
 g.DrawImage(block, x, y); //drawing the new block over the inital image.
 this.Invoke(new Action(() => pictureBox1.Refresh())); //refreshing the picturebox-will update the intial;

 }
}
  private Bitmap bufferToJpeg()
    {
      return (Bitmap)Image.FromStream(ms);        
    }

I'm getting an error

object is currently in use elsewhere

On the Graphics creation line

Graphics g = Graphics.FromImage(initial);

I'm not using any other threads or somthing ot access the bitmap..so i'm not sure what's the problem here..

If anyone can enlighten me i'll be really thankful.

Thanks.

Try to assign the graphics before the loop:

private void MainScreenThread() {

  ReadData();
  initial = bufferToJpeg(); 
  pictureBox1.Image = initial;
  Graphics g = Graphics.FromImage(initial);

  while (true) {
    int pos = ReadData();
    int x = BlockX();
    int y = BlockY();
    Bitmap block = bufferToJpeg(); 

    g.DrawImage(block, x, y); 
    this.Invoke(new Action(() => pictureBox1.Refresh())); 

  }
}

Its because you never dispose the graphics object after its being used.

If you look at the graphics component, when you create it. You use the "initial" bitmap. The graphics are now pointing at this "initial" object, first time it will succeed to create the graphics but second time (since the 'g' has not been disposed/been released) the "initial" object is still being in use by the old graphics before creating a new one.

What you can do is:

private void MainScreenThread() {

   ReadData();
   initial = bufferToJpeg(); //full screen first shot.
   pictureBox1.Image = initial;

   while (true) {
    int pos = ReadData();
    int x = BlockX();
    int y = BlockY();
    Bitmap block = bufferToJpeg(); //retrieveing the new block.

    using(Graphics g = Graphics.FromImage(initial)) {
       g.DrawImage(block, x, y); //drawing the new block over the inital image.
       this.Invoke(new Action(() => pictureBox1.Refresh())); //refreshing the picturebox-will update the intial;
   }
 }
}

What will happen is that the 'g' object will be disposed after being used so that you can do the same operation again afterwards.

Edit : Fix- Didnt properly include the whole code as a code block.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM