2016-07-06 11 views
2

私はプロジェクトに取り組んでいます。すでに存在するイメージのソケットから受け取ったイメージのブロック(ビットマップとして)を描画する必要があります)、それをPictureBoxに表示する - つまり、新しいブロックを受け取るたびにイメージを更新することです。c#ビットマップを別のものに描画する

これを非同期で実行するには、Socketからデータを読み込んで処理するThreadを使用します。

この

は私のコードです:

オブジェクトがGraphics作成ライン上の他の場所

現在使用中である

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

私はエラーを取得しています

Graphics g = Graphics.FromImage(initial); 

私は他のスレッドを使用していないか、ビットマップにアクセスしていません。ここで何が問題なのかよくわかりません。

誰かが私を啓発できれば、本当に感謝します。

ありがとうございました。

+0

あなただけのPictureBoxもBitmapクラスでもないが、スレッドセーフであることを発見。 Bitmapクラスには、PictureBoxが再描画するのとまったく同時にGraphics.FromImage()を使用すると、kaboomのためにそのための診断が組み込まれています。ランダムな、スレッドレースバグのようなものはいつもあります。 Graphics.FromImageとDrawImageというコードをさらに呼び出す必要があります。独自のスレッドセーフPictureBoxクラスを作成する場合、そのOnPaint()オーバーライドでは、このメソッドでも取るロックを行う必要があります。 –

+0

これでかなり早く 'OutOfMemoryException'を実行することになるでしょう。各ループ内に' block'を配置し、実行したら 'g'を処分する必要があります。 –

答えて

1

試してみてください。

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

グラフィックスオブジェクトは、使用後に決して処理しないためです。

グラフィックスコンポーネントを作成するときは、そのコンポーネントを作成します。あなたは "初期"ビットマップを使用します。グラフィックスは現在、この「初期」オブジェクトを指しています。最初にグラフィックを作成するのに成功しますが、「g」はまだリリースされていないため、「初期」オブジェクトはまだ使用されています。新しいグラフィックを作成する前に古いグラフィックスを保存します。あなたは何ができるか

は次のとおりです。

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

何が起こるだろうことは「G」オブジェクトを使用すると、その後再び同じ操作を行うことができるように使用された後に配置されるということです。

を編集します。修正 - コード全体をコードブロックとして正しく含めませんでした。ループの前にグラフィックスを割り当てる

+0

私もそれについて考えていたので、以前は 'Dispose'を使っていましたが、今は' Using() 'ステートメントを使っています...残念ながら、まったく同じエラーが発生しています。現在他の場所で使われています@Karl Patrik Johansson – Slashy

+0

ええと、それは絵の箱で使われているからでしょうか?おそらく、グラフィックを作成する前に最初のビットマップを試して複製し、複製されたビットマップを新しい画像としてピクチャボックスに割り当てます。 ex: 'var img =(ビットマップ)initial.Clone(); (新しいアクション()=> pictureBox1.Image = img)); ' –

+0

今、私はクローンの作成時にエラーが発生しています(グラフィックスg = Graphics.FromImage(img)この行で 'var img =(Bitmap)initial.Clone();' @Karl Patrik Johansson – Slashy

関連する問題