2016-12-08 3 views
3

그래서있어 여기 foreach 루프는 .Dispose()가 foreach 루프에서 동작하지 않습니다

foreach (string file in condensedFilesList) 
{ 
    Image imgToAdd; 
    imgToAdd = Image.FromFile(file); 

    if (imgToAdd.Width < 1920 || imgToAdd.Height < 1080) 
    { 
     //neither of the commented out lines worked when placed here 
     //imgToAdd = null; 
     //imgToAdd.Dispose(); 
     condensedFilesList.Remove(file); 
    } 
    else 
    { 
     //neither of the commented out lines worked when placed here 
     //imgToAdd = null; 
     //imgToAdd.Dispose(); 
     continue; 
    } 
} 

그것은 .JPG 이미지를 가리키는 파일 경로의 목록이 포함되어 있습니다. 약 80 종류의 다양한 크기. 각 이미지를 살펴보고 그 해상도가 1920 * 1080인지 확인하고 그렇지 않은 경우 파일 경로 포인터를 배열에서 제거하십시오.

지금 imgToAdd 변수에서 검토 할 이미지를 설정 한 다음 width 속성이나 height 속성이 해당 항목이 제거 될 항목과 일치하지 않으면 처리가 진행됩니다. 이것은 첫 번째 항목에 적용됩니다. 해상도가 청구서에 맞지 않아 배열이 80 개에서 79 개로 줄어 들었습니다.

그러나 imgToAdd 변수를 비워서 새 filePath를 할당 할 수 없습니다. OutOfMemoryException이 계속 실행됩니다. 나는 .Dispose()를 null로 설정하여 실행하려고 시도했지만 실제로 리소스 자체를 비우지 못한다.

디버거에서 .Dispose()는 요소를 검사 할 때 imgToAdd가 값 대신 긴 오류 목록을 갖게합니다. 그것의 속성은 모두 존재하지만 가치가 없으며 오류로 대체됩니다. null로 설정하면 작동하지만 다음 반복에서는 imgToAdd = null이됩니다. Buuuuut, 변수에 새 filePath를 할당하려고하면 OutOfMemoryException이 발생합니다.

그래서 나는 그것에 관해 어떤 단서도 가지고 있지 않습니다. 나는 다른 사람들이 내가 잘못하고있는 것을 지적 할 수 있기를 기대하고있다. 나는 그것을 볼 수 없다.

EDIT2 : 난 그냥 사람들이 내가 업데이트와 기능의 진화를 확인하려는 경우,이 편집 공간을 덮어 쓸거야

, 편집 역사를 기록했다. @dlatikay와 같은 using() {} 문을 사용하여 시도해 보았고 새 목록을 작성했습니다.하지만 불행히도 OutOfMemoryException이 발생합니다. 여기에 기능을 그건 바로 당신이 또한 당신이 컬렉션을 수정에 대한 시간 오류를 실행하는거야 문제의 시작 인 그 위에 메서드를 호출하기 전에 null에 변수를 설정의 상단에

 var tempList = new List<string>(); 

     foreach (string file in condensedFilesList) 
     { 
      using (Image imgToAdd = Image.FromFile(file)) 
      { 
       if (imgToAdd.Width < 1920 || imgToAdd.Height < 1080) 
       { 
        continue; 
       } 
       else 
       { 
        tempList.Add(file); 
       } 
      } 
     } 

     condensedFilesList = tempList; 
+1

전에 처분을 호출 = null –

+0

즉 .. imgToAdd.배출(); 다음 imgToAdd = null; –

+3

FYI 반복중인 컬렉션을 수정할 수 없습니다. 반복 할 임시 콜렉션을 생성하거나 끝에 시작하여리스트의 앞쪽에서 작동하는'for' 루프를 수행해야합니다. – juharr

답변

4

using을 사용하십시오. 를 열거하는 동안 소스 목록을 수정되지 않도록 그리고, 새로운 목록에 결과를 쓰기 :

var finalList = new List<string>(); 
foreach (string file in condensedFilesList) 
{ 
    using(var imgToAdd = Image.FromFile(file)) 
    { 
     if (imgToAdd.Width < 1920 || imgToAdd.Height < 1080) 
     { 
      /* omit */ 
     } 
     else 
     { 
      finalList.Add(file); 
     } 
    } 
} 

널 (null)을 할당, 또는 명시 적으로() 폐기를 호출 할 필요합니다. try..catch를 추가하는 것이 좋습니다. 모든 이미지 파일이 유효하지는 않습니다.

+0

Hey man, 방금이 메모리 오류가 발생했습니다. 편집 영역에 가장 최신 버전의 기능을 추가했습니다. 어떤 아이디어?/: – Chris

+0

OP에 대한 마지막 코멘트보기 – dlatikay

4

반복. 다음은 코드가 제대로 작동하도록 작성하는 방법입니다.

foreach (string file in condensedFilesList.ToList()) 
{ 
    using(var imgToAdd = Image.FromFile(file)) 
    { 
     if (imgToAdd.Width < 1920 || imgToAdd.Height < 1080) 
     { 
      condensedFilesList.Remove(file); 
     } 
    } 
} 

ToList는 안전하게 condensedFilesList.Remove을 사용할 수 있도록 반복하기 위해 별도의 컬렉션을 만들 것입니다. imgToAddusing 문에 입력하면 Dispose을 호출 할 때 더 이상 걱정할 필요가 없으므로 예외가 발생해도 문 끝에서 호출됩니다.

+0

경험에 의하면,이 ToList() 트릭은 주석과 함께 가야합니다. 나는 잠시 후 코드를 다시 보았을 때 개발자가 너무 자주 제거했다는 것을 알았습니다. 개발자들은 "이미 목록입니다. 목록이 필요합니다. * 제거 *, 체크 인, 죄송합니다." – dlatikay

0

목록이 열거 될 때 목록에서 항목을 제거 할 수 없습니다.

for (int i = condensedFilesLists.Length - 1; 0 <= i; --i) 
{ 
    using (var image = Image.FromFile(condensedFilesLists[i])) 
    { 
     if (image.Width < 1920 || image.Height < 1080) 
     { 
      condensedFilesList.Remove(file); 
     } 
    } 
}