2016-07-06 6 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 클래스에는 PictureBox가 자체적으로 다시 칠하는 동시에 Graphics.FromImage()를 사용할 때 kaboom에 대한 진단 기능이 내장되어 있습니다. 꽤 무작위로, 스레딩 경주 버그가 항상 있습니다. Graphics.FromImage 및 DrawImage와 같은 코드를 더 호출해야합니다. 또는 자신 만의 스레드 세이프 (thread-safe) 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() 문을 사용합니다 ... 불행히도 동일한 오류가 발생했습니다 .... 같은 줄에 ... 객체가 있습니다. 현재 다른 곳에서 사용 중'Kll Patrik Johansson – Slashy

+0

흠, 그림 상자에서 사용 중이니까요?아마도 그래픽을 생성하기 전에 초기 비트 맵을 복제하고 복제 한 다음 복제 된 비트 맵을 그림 상자에 새 이미지로 할당하십시오. ex :'var img = (비트 맵) initial.Clone(); (그래픽 g = Graphics.FromImage (img))'그리고 나서'this.Invoke (새로운 액션 (() => pictureBox1.Image = img)); ' –

+0

이제 클론 생성시 오류가 발생합니다. 이 줄에서'var img = (Bitmap) initial.Clone();'@Karl Patrik Johansson – Slashy