2009-11-20 3 views
10

패널에서 생성 된 전역 그래픽 객체가 있습니다. 일정 간격으로 디스크에서 이미지를 가져 와서 Graphics.DrawImage()를 사용하여 패널에 그립니다. 그것은 몇 반복을 위해 잘 작동하고 나는 다음과 같은 도움이 예외를 받고 있어요 : 나는 그것으로 끝났어요 때 이미지 객체의 처분으로 내가 메모리 누수를 배제이미지를 그릴 때 : System.Runtime.InteropServices.ExternalException : GDI에서 일반적인 오류가 발생했습니다.

System.Runtime.InteropServices.ExternalException: A generic error occurred in GDI+. 
at System.Drawing.Graphics.CheckErrorStatus(Int32 status) 
at System.Drawing.Graphics.DrawImage(Image image, Int32 x, Int32 y) 
at System.Drawing.Graphics.DrawImage(Image image, Point point) 

합니다. 나는 이미지가 손상되지 않았으므로 패널이 멈추기 전에 프로그램이 잘 실행되면 잘 읽혀질 수 있음을 안다.

PictureBox를 사용할 때 동일한 문제가 발생했지만 이번에는 아무 것도 표시하지 않고 오류가 발생했습니다.

작업 관리자에서 GDI 개체와 USER 개체를 확인했지만 응용 프로그램이 작동 할 때와 사용하지 않을 때 항상 약 65 개의 사용자 개체와 165 개의 GDI 개체가 있습니다.

.NET Framework 라이브러리에서 중단 점을 지정하고 정확히 실행이 실패한 곳을 확인할 수있는 것과 같이 나중에이 바닥에 도달해야합니다.

미리 감사드립니다.

EDIT는 :

private void DrawImage(Image image) 
{ 
    Point leftCorner = new Point((this.Bounds.Width/2) - (image.Width/2), (this.Bounds.Height/2) - (image.Height/2)); 
    _graphics.DrawImage(image, leftCorner); 
} 

화상 부하 코드 :

private void LoadImage(string filename, ref Image image) 
{ 
    MemoryStream memoryStream = DecryptImageBinary(Settings.Default.ImagePath + filename, _cryptPassword); 

    image = Image.FromStream(memoryStream); 

    memoryStream.Close(); 
    memoryStream.Dispose(); 
    memoryStream = null; 
} 

_image 전역하고 그 기준은 LoadImage 갱신되어 이는 디스플레이 코드이다. 전역 참조를 가능한 한 소수의 장소에서 변경하고 다른 메소드를 자체적으로 포함하려는 경우 매개 변수로 전달됩니다. _ 그래픽도 글로벌입니다.

웹 사이트 용 webBrowser 컨트롤도 있는데 한 번에 이미지 또는 웹 사이트를 표시합니다. 화상을 표시하는 시간이있을 때, 다음 코드 실행 :

webBrowser.Visible = false; 
panel.Visible = true; 
DrawImage(_image) 
_image.Dispose(); 
_image = null; 

_image은 사전로드 된 화상을 참조한다.

희망이 도움이됩니다.

답변

14

귀하의 문제는 내가 생각했던 것과 유사하다 ... 어떤 임의의 지점에서 실패하지만, 꽤됩니다 . 이미지를로드 할 때 MemoryStream에서 이미지를로드하고 있습니다. 이미지 수명 동안 스트림을 열어 두어야합니다 (MSDN Image.FromStream 참조).

이미지를 사용하는 동안 스트림을 열어 두어야합니다.

솔루션은 FromImage 기능에 이미지의 복사본을 만드는 것입니다 :

내가 언급 한 이미지가 제대로 작동하고 무작위로 실패합니다 처분 문제에 대한 유사
private void LoadImage(string filename, ref Image image) 
{ 
    using (MemoryStream memoryStream = DecryptImageBinary(Settings.Default.ImagePath + filename, _cryptPassword)) 
    { 
     using (tmpImage = Image.FromStream(memoryStream)) 
     { 
     image = new Bitmap(tmpImage); 
     } 
    } 

} 

때 기본이되는 스트림 쓰레기 수거.

+0

나는 그것을 시험해 볼 것이다, 고마워. tmpImage를 명시 적으로 처리 할 필요가 없습니까? memoryStream의 처리는 기본 이미지도 처분 할 수 있습니까? – Michali

+0

그래, memoryStream을 처리하면 대부분의 기본 데이터가 가비지 수집되지만, tmpImage를 명시 적으로 처리해야합니다. 나는 그것을 보여주기 위해 대답을 바꾸었다. –

+0

감사합니다. 그것은 그것을 해결 한 것으로 보인다. – Michali

2

좀 더 많은 코드가 없으면 여기를 제대로 진단 할만큼 충분하지 않습니다. 그러나 한 가지 살펴볼 점은 이미지를 드로잉 한 시점에서 어느 시점에 처리했을 수 있으며 가비지 수집기 코드가 실행되지 않습니다. 어디에서나 복제 된 이미지를 사용하고 있습니까? 내가 배울 수있는 한 가지 사실은 이미지의 똑 바른 clone을 수행하면, 이미지가 의존하는 기본 비트 맵을 복제하지 않고 이미지 구조 만 생성하여 이미지의 적절한 복사본을 만들어야한다는 것입니다. 새 이미지 :

var newImage = new Bitmap(img) 

var newImage = oldImg.Clone(); 
oldImg.Dispose(); 
... 
gr.DrawImage(newImage, new Rectangle(0,0,newImage.Width,newImage.Height); 

잠시 동안 작동하지만 다음

+0

이제 더 많은 코드를 추가했습니다. 희망은 그 빛을 발산합니다. – Michali

+0

일을 명확히하기 위해 아래에 귀하의 문제에 대한 해답을 게시했습니다. –

관련 문제