2012-06-10 2 views
1

첫째, 코드 :이 파일 검색 스레드를 중단하는 것이 안전합니까?

lblFileNbr.Text = "?/?"; 
lblFileNbr.ToolTipText = "Searching for files..."; 
lock(_fileLock) 
{ 
    _dirFiles = new string[0]; 
    _fileIndex = 0; 
} 
if(_fileThread != null && _fileThread.IsAlive) 
{ 
    _fileThread.Abort(); 
} 
_fileThread = new Thread(() => 
    { 
     string dir = Path.GetDirectoryName(fileName) ?? "."; 
     lock (_fileLock) 
     { 
      _dirFiles = GetImageFileExtensions().SelectMany(f => Directory.GetFiles(dir, f, _searchOption)).OrderBy(f => f).ToArray(); 
      _fileIndex = Array.IndexOf(_dirFiles, fileName); 
     } 
     int totalFileCount = Directory.GetFiles(dir, "*.*", _searchOption).Length; 

     Invoke((MethodInvoker)delegate 
     { 
      lblFileNbr.Text = string.Format("{0}/{1}", NumberFormat(_fileIndex + 1), NumberFormat(_dirFiles.Length)); 
      lblFileNbr.ToolTipText = string.Format("{0} ({1} files ignored)", dir, NumberFormat(totalFileCount - _dirFiles.Length)); 
     }); 
    }); 
_fileThread.Start(); 

나는 작은 이미지보기 프로그램을 짓고 있어요. 이미지를 열면 동일한 디렉토리에있는 파일 수가 나열됩니다. 다른 파일 (예 : 150K)이 많은 디렉토리에서 이미지를 열면 파일 목록을 작성하는 데 몇 초가 걸립니다. 따라서이 작업을 다른 스레드에 위임합니다.

그러나 파일 검색을 완료하기 전에 다른 이미지를 열면 이전 카운트는 더 이상 적합하지 않으므로 스레드를 중단합니다.

내가 사진 사이를 전환 할 몇 가지 왼쪽오른쪽 키 기능을 추가하려는 때문에 _dirFiles_fileIndex 잠금, 그래서 나는 다른 곳에서 그 액세스해야합니다 (그러나 UI 스레드에서).

안전한가요? C#에서 스레드를 다루는 수십 가지 방법이있는 것처럼 보입니다. 저는 단순한 것을 원했습니다.


fileName는 (? 오른쪽은 익명 함수에 "복사"됩니다 의미) 지역 변수이며, _searchOption는 읽기 전용, 그래서 나는 그 둘은 접근 안전 상상한다.

답변

3

>이 파일 검색 스레드를 중단해도 안전합니까?

짧은 답변은 입니다.

스레드를 중단하는 것이 거의 절대 안전하지 않으며,이 조언은 네이티브 코드를 실행할 때 더 많이 적용됩니다.

시간이 걸리는 Directory.GetFiles에 대한 전화이므로 협조적으로 빨리 종료 할 수없는 경우 가장 좋은 방법은 스레드를 포기하는 것입니다. 정상적으로 끝내지 만 결과는 무시하십시오.

은 언제나처럼, 나는 Joe Albahari's free ebook

+0

+1. ** 작성하지 않은 코드는 절대 중단 할 수 없습니다 **. – usr

+0

Hrm ... 만약 내가 그들을 중단하지 않으면 당신은 수십 개의 열린 스레드로 끝날 수 있습니다. 그, 그리고 나는 "콜백"동기화 밖으로 발사하지 않도록하기 위해 몇 가지 특별한 코드를 작성해야 겠어. – mpen

1

을 읽는 것은 Thread.Abort를 사용하여 스레드를() 중단 안전하지 않습니다 좋습니다. 하지만 대신 제어 된 방식으로 스레드를 안전하게 가져올 수있는 자체 중단을 구현할 수 있습니다.

GetFiles 대신 EnumerateFiles를 사용하는 경우 스레드를 중단해야하는지 여부를 확인하기 위해 플래그를 확인하면서 총 파일 수를 얻기 위해 카운터를 증가시킬 때 각 파일을 반복 할 수 있습니다. .

() 현재 GetFiles에 대신이 같은 무언가를 호출 길이 :

private bool AbortSearch = false; 
private int NumberOfFiles(string dir, string searchPattern, SearchOption searchOption) 
{ 
    var files = Directory.EnumerateFiles(dir, searchPattern, searchOption); 
    int numberOfFiles = 0; 
    foreach (var file in files) 
    { 
     numberOfFiles++; 

     if (AbortSearch) 
     { 
      break; 
     } 
    } 
    return numberOfFiles; 
} 

그런 다음

_fileThread.Abort(); 

AbortSearch=true; 
_fileThread.Join(); 

당신은 얻을 것이다 대체 할 수 현재 Thread.Abort()에서 무엇을하고 있는가?하지만 모든 스레드가 원할 때 끝내도록 허용합니다. 에.

+0

나는 그것에 대해 정확히 생각하고 있었지만, 거기에'.OrderBy'가 있음을 알게 될 것입니다. 나는 첫 번째 결과를 반환하기 전에 모든 것을 거쳐야한다고 생각합니다. 시간, 그리고 따라서 이것은 어떤 이익을 얻을 수는 없을 것이다 ....하지만 이제는 그것에 대해 생각하고, 나는 그것을 2 패스로 만들 수 있다고 가정하고 모든 파일을 먼저 열거한다 (열거를 통해) ... 수동으로 넣는다. 목록을 작성한 후 나중에 정렬하십시오. – mpen

+0

GetFiles의 두 인스턴스를 모두 EnumerateFiles로 변환 할 수 있다면 더 이상 실행 시간이 많이 걸리는 단 한 줄의 코드가 없으므로 빠르게 중단 할 수 있어야한다고 생각합니다. 아마도 파일 루프를 사용하여 루프를 반복해야하기 때문에 (파일 카운터를 사용하는) 결합 루프 내에서 모든 것을 시도 할 수도 있습니다. – SamLJG

+0

네, * 모든 * 파일을 열거하고 수동으로 필터링합니다. 그러면 루프를 한 번만 수행하면됩니다. 아마 나는 그것을 시도 할 것이다. – mpen

관련 문제