2016-07-06 13 views
2

Ich arbeite an einem Projekt, und ich muss Blöcke von Bildern (als Bitmaps) zeichnen, die ich von einem Socket auf einem bereits vorhandenen Bild (das ich am Anfang des Programms definiere)), und um es auf einem PictureBox anzuzeigen - mit anderen Worten, um das Bild jedes Mal zu aktualisieren, wenn ich einen neuen Block empfange.C# Bitmap über ein anderes zeichnen

Um dies asynchron zu tun, verwende ich eine Thread, die die Daten aus der Socket lesen und verarbeiten.

Dies ist mein 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);   
    } 

Ich

Objekt ist zur Zeit einen Fehler immer im Einsatz an anderer Stelle

Auf der Graphics Schaffung Linie

Graphics g = Graphics.FromImage(initial); 

Ich verwende keine anderen Threads oder etwas, das nicht auf die Bitmap..so ich bin mir nicht sicher, was das Problem hier ist ..

Wenn jemand mich erleuchten kann, werde ich wirklich dankbar sein.

Danke.

+0

Sie gerade entdeckt, dass weder die PictureBox noch die Bitmap-Klasse Thread-sicher sind. Glücklicherweise hat die Bitmap-Klasse eine Diagnose eingebaut, kaboom, wenn Sie Graphics.FromImage() zur selben Zeit verwenden, zu der sich die PictureBox selbst neu paintet. Ziemlich zufällig, wie Threading Race Bugs immer sind. Sie müssen mehr Code aufrufen, auch Graphics.FromImage und DrawImage. Oder erstellen Sie eine eigene threadsichere PictureBox-Klasse, deren OnPaint() - Überschreibung eine Sperre benötigt, die Sie auch bei dieser Methode verwenden. –

+0

Sie werden wahrscheinlich ziemlich schnell in eine 'OutOfMemoryException' hineinrennen, Sie müssen 'block' innerhalb jeder Schleife ablegen und' g' abschaffen, wenn Sie fertig sind. –

Antwort

1

Versuchen Sie, die Grafik vor der Schleife zuzuordnen:

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())); 

    } 
} 
-1

Dies liegt daran, dass Sie das Grafikobjekt nach seiner Verwendung nie verfügbar haben.

Wenn Sie die Grafikkomponente betrachten, wenn Sie es erstellen. Sie verwenden die "ursprüngliche" Bitmap. Die Grafik zeigt nun auf dieses "initiale" Objekt, beim ersten Mal gelingt das Erstellen der Grafik, aber beim zweiten Mal (da das 'g' nicht freigegeben wurde) wird das "initiale" Objekt immer noch von der alte Grafiken vor dem Erstellen eines neuen.

Was können Sie tun, ist:

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; 
    } 
} 
} 

Was passiert, ist, dass das ‚g‘ Objekt wird nach dem so verwendet wird, angeordnet sein, dass Sie den gleichen Vorgang danach wieder tun können.

Bearbeiten: Fix- Didnt ordnungsgemäß den gesamten Code als Codeblock enthalten.

+0

Ich habe auch darüber nachgedacht, also habe ich 'Dispose' vorher verwendet, und jetzt benutze ich die' Using() 'Anweisung ... leider bekomme ich genau den gleichen Fehler .... in der gleichen Zeile ...' Objekt ist derzeit im Einsatz anderswo @Karl Patrik Johansson – Slashy

+0

Hmm, dann muss es sein, weil es von der Bilderbox verwendet wird?Versuchen Sie vielleicht, die ursprüngliche Bitmap zu klonen, bevor Sie die Grafiken erstellen, und weisen Sie die geklonte Bitmap als neues Bild der Bildbox zu. Beispiel: 'var img = (Bitmap) initial.Clone(); benutze (Grafik g = Graphics.FromImage (img)) 'und dann' this.Invoke (new Action (() => pictureBox1.Image = img)); ' –

+0

jetzt bekomme ich den Fehler bei der Erstellung des Klons in dieser Zeile 'var img = (Bitmap) initial.Clone();' @Karl Patrik Johansson – Slashy

Verwandte Themen