2011-09-15 2 views
2

그림 데이터베이스와 슬라이드 쇼인 두 개의 Windows Form 프로그램이 있습니다.Visual Studio 2010의 메모리 부족 문제 Visual Basic .Net 4.0

슬라이드 쇼가 지속적으로 사진의 새 스위치와 함께 사용되는

메모리를 증가없이 표시에 PictureBox를 업데이트합니다. 그러나 나는 두 번째 형식이 있습니다

에는 데이터베이스에 추가 할 그림의 축소판을 표시하기위한 50 개의 그림 상자가 있습니다. 크기 (57,40)의 각 그림 상자가 작은 축소판 그림 (< 12K)으로 업데이트됨에 따라 IDE에서 사용되는 메모리는 내 32 비트 XP 시스템에서 약 660MB에서 1GB가 조금 넘게 올라가며 축소판 그림 상자가로드됩니다 .

크기 (57,40)의 약 30 개가 .jpg 소스 파일에서 3MB 이상로드되면 IDE 메모리 사용이 약 2.1GB로 증가합니다. (문제는 쉽게 .jpg 이미지와 함께 발생하지 않습니다. < = 15K 및 모든 50 축소판은 < 1.3GB mem 사용시 사용 가능).

문제는 그 자체가 평균 .jpg 파일 크기> 3MB의 HD 캐논 카메라 .jpg 이미지가 표시된 축소판 그림 상자 30 개에로드되어 표시되는 그림 선택을 시작하고 사용 된 메모리가 빠르게 2.3GB 메모리 사용량 초과로 인해 메모리 부족 현상이 발생합니다.

VB2010 또는 .NET 4.0의 버그입니까?

모든 사진이 축소판으로 표시되면 모든 축소판을 포함하는 패널의 50 개 그림 상자 중 하나를 마우스로 클릭하면 양식에 하나의 큰 그림 상자가 업데이트되어 크기가있는 단일 그림 상자에 그림이 표시됩니다 1024,768). 썸네일을 클릭하면 하나의 큰 그림 상자에 파일의 관련 그림이 표시되지만 동시에 시스템 메모리는 클릭 이벤트 당 약 240KB 씩 증가합니다. 결국 시스템 메모리가 약 2.3GB를 초과하면 프로그램이 메모리 부족 오류로 인해 충돌합니다.

어떻게

가 또 다른 사진과 함께 업데이트 될 때 같은 PictureBox를 사용하는 메모리를 복구 할 수있는 프로그램을 얻을 수 있나요? 아래

부분 코드 : I가 설치 XP PRO 32-Bit SP3 4GB RAMVisual Studio Ultimate SP1 updated .NET 4.0을 사용하고

' Each Thumbnail has a click event 
'PB49 is a PictureBox max size (57,40) used as a thumbnail display, all 50 are on a panel 
Private Sub PB49_Click(sender As System.Object, e As System.EventArgs) Handles PB49.Click 
    'PB(50) is an Integer Array flagging Pictures to add 
    If PB(49) = 1 Then PB(49) = 0 Else PB(49) = 1 
    If PB(49) = 1 Then 
     CheckBox49.Checked = True  'Tiny Checkbox on thumbnail 
     F$ = ListAddFiles.Items(48)  'ListFileBox of FileNames 
     PBx1.Image = Image.FromFile(F$) 'Gets filename and path and loads image into PictureBox 
     PBx1.Visible = True 'Large PictureBox (1024,768)shows Pic F$ located on Form 
    Else 
     CheckBox49.Checked = False 
     PBx1.Image = Nothing 
     PBx1.Visible = False 
    End If 
End Sub 

.

+0

당신이 배치 될 필요가있는 객체를 폐기하고 있습니까? –

+0

질문에'?'를 너무 많이 사용하면 안됩니다. – VMAtm

+0

그리고 이것은 VS가 아니라 귀하의 버그입니다. – VMAtm

답변

2

이미지를 숨길 때 이미지를 다시로드 할 수 있습니까? 나는. 당신은 그것을 숨기고, 숨겨진 사람은 거기 머물러 있으며, 나중에 다시 추가됩니다. 그러므로 당신은 엄청난 수의 숨겨진 이미지를 축적하고 있습니까?

.NET 응용 프로그램의 "메모리 누수"는 종종 참조를 없애거나 모든 컬렉션에서 개체를 제거하지 않은 결과입니다. 객체가 어딘가에서 참조를 가지고있는 한, 폼의 컨트롤 컬렉션에있는 컨트롤이거나 자신의 컬렉션 중 하나 인 경우에는 메모리에 남아 있습니다. 나는 당신이 논리가 그림을 보이거나 감추기 위해 무엇인지 모르겠다. 그러나 아마도 당신은 그림을 제거하고 모든 관련 컨트롤에서 그것에 대한 참조를 분명히 할 필요가있을 것이다. 컨트롤 컬렉션을 중첩 할 수있는 방법으로 장소를 놓치기 쉬울 것입니다. 아마도 이미지 관련 컨트롤에 추가적인 오버 헤드가있을 수 있습니다. 따라서 사용되지 않는 컨트롤이 많이 숨겨져 있지만 메모리에 앉아 있으면 문제가 될 수 있습니다.

당신은 50 개의 그림 상자가 있지만 표시되지 않은 모음보다 그림이 많다고 말합니다. 컬렉션에로드 한 경우 표시되는지 여부에 관계없이 메모리를 차지할 수 있습니다.

몇 가지 알아 두어야 할 사항.

1) 32 비트 Windows의 프로세스에는 최대 2GB의 메모리가 있습니다. 이것을 기계에서 3GB로 구성하는 방법이 있지만 일반적으로 2GB 이상을 사용할 수는 없습니다. Ojn 그 외에 정상적인 메모리 단편화로 인해 많은 여유 메모리가있는 경우에도 OutOfMemory 예외가 발생할 수 있습니다.

2) .NET 콜렉션을 처리 할 때마다 일반적으로 내부적으로 배열로 구현됩니다. 배열은 인접한 메모리 블록입니다. 따라서 많은 여유 메모리가 있더라도 조각화로 인해 충분한 연속 메모리 블록이 없기 때문에 OutOfMemory 예외를 얻을 수 있습니다. .NET은 조각 (fragementation)을 줄이기 위해 노력하지만 때로는 혼잡 한 방에서 거대한 책상을 움직이는 것과 같으며 기적을 일으킬 수 없습니다.

3) 배열은 동적으로 확장되지 않으므로 내부적으로 컬렉션은 공간이 부족할 때마다 새 배열을 배치해야합니다. 일반적으로 매회 배열 크기가 두 배가됩니다. 이것은 대부분의 콜렉션의 "용량"속성입니다. 일부 디버깅을 사용하여 .Capacity 및 .Length 컬렉션을 모니터링해야합니다. 컬렉션이 그 크기에 도달 할 때마다 두 번 관찰하게됩니다. 나는. 128, 256 등

언제든지 새 배열을 할당 한 다음 이전 배열의 할당을 해제하기 전에 이전 배열의 내용을 복사해야합니다. 따라서 256 (또는 64와 같은 2의 다른 2의 거듭 제곱)을 가진 콜렉션이 있고 하나 이상의 항목을 추가 한 경우 내부적으로 콜렉션은 새로운 512 항목 배열을 할당 한 다음 이전 배열에서 그 안에 복사합니다. 이 전환 과정에서 512 및 256 어레이가 모두 메모리에 있습니다. 따라서 257 번째 항목을 추가하기 위해서는 257 번째 항목에 대한 공간 만 필요하지만 3 번째 항목 (256 + 512 = 768)이 필요합니다.

콜렉션에 그림을 추가하는 동안 예외가 발생하는지 여부를 판별하려면 스택 추적을 사용하십시오. 필요하면 콜렉션이 확장되는 시간을 추가합니다. 또한 통화가 2의 거듭 제곱이되기 바로 전에 길이를 알 수 있습니다.

그래서 이미지를 512MB로하고 컬렉션을 확장해야 할 경우 .NET에서 1GB 어레이를 할당 할 공간을 찾아야합니다 의 이미지. 따라서 용량을 확장해야하는 컬렉션의 전환 중에 1.5GB의 RAM이 필요합니다. NET에서 단편화로 인한 1GB의 연속 블록을 발견하는 것은 매우 어려울 것입니다. 단편화를 최소화하기 위해 .NET에서 모든 단계를 거치더라도 여전히 제어가 많이 있습니다. (누군가는 아마 참조의 배열은 훨씬 작은 것을 지적 할 것이다, 그러나 당신이 다루고있는 무슨 말을하기 어렵다.)

솔루션 : 이이 문제의 원인, 다음 솔루션 판단되는 경우 얼마나 많은 항목이 필요한지 예측하고 사전에 배열의 용량을 설정하는 것입니다. 따라서 이미지 목록이 있다면 먼저 해당 이미지 수를 얻은 다음 컬렉션 용량을 그 양으로 설정하는 것이 좋을 것입니다. 아마도 10 % 더 많거나 더 많을 수도 있습니다. 이렇게하면 300 개의 항목이있는 경우 용량을 350으로 설정할 수 있습니다. 대신 약간의 헤드 룸을 사용하여 미리 용량을 예측 한 다음 확장하지 않아도되므로 3 배의 스파이크가 발생하지 않습니다. 확장을위한 메모리 사용.

Google. NET 메모리 프로파일 러. 많은 프로파일 러가 있으며 또한 메모리 할당과 할당 해제 및 조각화에 대한 세부 정보를 볼 수있는 디버그를 얻습니다.

+0

코드에서 발견 된 문제. – VMAtm

2

@AaronLS는 궁극적 인 teoretic 대답을주었습니다.
코드에서 메모리 누수가 여기에 있습니다 : 당신이 Image.FromFile 방법을 사용으로

PBx1.Image = Nothing 
PBx1.Visible = False 

PBx1.Image는 Image 유형의 객체입니다. ImageIDisposable이며 비 관리 코드의 네이티브 리소스를 사용한다는 의미입니다.

명시 적으로이 코드에 PBx1에 대한 .Dispose() 메서드를 호출해야합니다 :

'PBx1.Image = Nothing 
If PBx1.Image IsNot Nothing Then PBx1.Image.Dispose() End If 
PBx1.Visible = False