2016-08-29 2 views
2

C#으로 코딩 된 내 이미지 뷰어에 다음 및 이전 탐색 옵션을 추가 할 때 약 20 분 후에 다음을 누르면 Visual Studio에서 프로세스의 메모리가 부족하다고 알립니다. .Image.Dispose 사용에도 불구하고 이미지 뷰어에서 메모리 부족 메모리 부족.

유형의 처리되지 않은 예외 'System.OutOfMemoryException이'는 System.Drawing.dll 추가 발생

: 그것은 그들 모두에 대한 이미지 파일 크기가

내가 얻을 작은 경우에도 많은 어떤 폴더에이 작업을 수행 정보 : 메모리가 부족합니다.

은, 내가 그것을 사용했다이 다른 사람에 대해 검색 한 때문에 ibread_img.Image.Dispose();이 가지고 당신이 볼 수 있듯이 이제

private void next_Click(object sender, EventArgs e) 
{ 
    string[] foldernm = Directory.GetFiles(Path.GetDirectoryName(lfoto_file.FileName)); 
    _pictureIndex++; 
    if (_pictureIndex >= foldernm.Length) 
    { 
     _pictureIndex = 0; 
    } 
    ibread_img.Image.Dispose(); 
    ibread_img.Image = Image.FromFile(foldernm[_pictureIndex]); 
} 

을 사용하고있는 코드이지만, 그것은 작동하지 않습니다 여전히 같은 문제가 발생하면 코드가 실행되고있어 메모리가 부족한 이유를 혼란스럽게합니다. 사이클링중인 이미지가 크지 않습니다. 나는 이전에로드 된 이미지를 nulling하는 것, 수동으로 가비지 콜렉터를 호출하는 것을 포함하여 찾을 수있는 모든 것을 시도했지만 아무것도 작동하지 않는 것 같습니다. 나는 C#에서 최선이 아니므로 그 코드에 끔찍한 실수 나 결함이있을 수 있지만 모르겠다. 이것을 고치는 방법에 대한 아이디어는 무엇인가?

+3

실제로 유효한 이미지 파일이 있는지 확인 하시겠습니까? – LarsTech

+0

예외가 발생한 후에도 이미지가 그려지고 있습니까? 그렇다면 다음과 같이 중복 될 수 있습니다. http://stackoverflow.com/questions/6506089/system-drawing-out-of-memory-exception – JDupont

+1

로드 할 가능성이 높은 검색 패턴/필터가 지정되어 있지 않으므로 이미지 파일. – Plutonix

답변

1

시청자를 개선하기 위해 할 수있는 몇 가지 방법이 있습니다. 먼저, 매번 이미지 파일 목록을 다시 만들고 있습니다. 당신은 다음 번에 액세스하기 위해 매번 그 모든 것을로드하고 있으며 그것을 보여주기 위해 이미지를 생성하지 않아도됩니다.

// class level vars 
int picIndex = 0; 
IEnumerable<string> files; 
int filesCount; 
string picPath; 
static string[] imgExts = {".png", ".jpg",".gif"}; 

다음 및 이전 버튼에 대해 언급 했으므로 다른 곳에서 거의 동일한 코드가 있어야합니다.

ShowImage(picIndex); 

picIndex+=1; 
if (picIndex >= filesCount) 
    picIndex = 0; 

는 그런 방법은 원하는 이미지를 보여줄 수 : (2 곳) 파일의 목록을 각 시간을 만들

private void ShowImage(int Index) 
{ 
    // create image list if needed (once) 
    if (files == null) 
    { 
     files = new DirectoryInfo(picPath).EnumerateFiles(). 
      Where(q => imgExts.Contains(q.Extension.ToLowerInvariant())). 
      Select(z => z.FullName); 

     filesCount = files.Count(); 
    } 

    string thisFile = files.ElementAt(Index); 

    // no need to dispose an image if you never create one   
    pb2.ImageLocation = thisFile; 
    lblImgName.Text = Path.GetFileName(thisFile); 
} 

대신을이 그것을 한 번 지금까지 수행이는 중복, 다음을 제거합니다 모든 목록을로드하는 대신 필요에 따라이를 가져 오려면 IEnumerable으로 남겨 둡니다. 또한 FileInfo에서 작동합니다. 대/소문자를 구분하지 않고 원하는 경우 원하는 날짜에 따라 (OrderBy) 정렬 할 수있는 다른 방법을 보여줍니다.

마지막으로 전체 경로와 파일 이름이 주어지면 .ImageLocation 속성을 사용하고 Image의 생성 및 삭제를 피할 수 있습니다.

중요한 것은 반복되는 코드의 양을 최소화하여 Dont Repeat Yourself입니다. 다음 및 이전 코드는 거의 동일합니다.

+0

고맙다. 나는 네가 말한 것을 시도 할 것이다. 나는 가능한 한 내 코드를 선택하고 합리화하고 싶다. – Kai

0

내 실수를 지적 해 준 LarsTech와 Plutonix에게 감사드립니다. 이 새로운 코드는 현재 정상적으로 작동합니다.

private void next_Click(object sender, EventArgs e) 
    { 
     var filteredFiles = Directory.EnumerateFiles(Path.GetDirectoryName(lfoto_file.FileName)) 
      .Where(file => file.ToLower().EndsWith("jpg") || file.ToLower().EndsWith("png") || file.ToLower().EndsWith("gif") || file.ToLower().EndsWith("bmp") || file.ToLower().EndsWith("tiff") || file.ToLower().EndsWith("ico")) 
      .ToList(); 
     _pictureIndex++; 
     if (_pictureIndex >= filteredFiles.Count) 
     { 
      _pictureIndex = 0; 
     } 
     ibread_img.Image.Dispose(); 
     ibread_img.Image = Image.FromFile(filteredFiles[_pictureIndex]); 
     init(); 
    } 

올바른 형식을 필터링하기 만하면됩니다.