2013-05-28 1 views
3

내 응용 프로그램에서 내 목록 상자에 추가하기 전에 열린 Wireshark 프로세스로 파일을 검사합니다. 이이 폴더 및 하위 폴더 안에 디렉토리를 클릭 루트 폴더를 취할 이벤트 및 확인이 모든 파일을 추가입니다 :내 BackgroundWorker가 끝날 때까지 기다려 새 BackgroundWorker를 엽니 다.

나는 많은 파일과 폴더를 선택하는 경우 그래서 개방 Wireshark 과정입니다이 파일을 확인하고
private void btnAddDir_Click(object sender, EventArgs e) 
{ 
    try 
    { 
     if (folderBrowserDialog1.ShowDialog() == DialogResult.OK) 
     { 
      ThreadStart threadStart = delegate 
      { 
       foreach (string file in SafeFileEnumerator.EnumerateFiles(folderBrowserDialog1.SelectedPath, "*.*", SearchOption.AllDirectories)) 
       { 
        Interlocked.Increment(ref numWorkers); 
        StartBackgroundFileChecker(file); 
       } 
      }; 

      Thread thread = new Thread(threadStart); 
      thread.IsBackground = true; 
      thread.Start(); 
     } 
    } 
    catch (Exception) 
    { } 
} 

private void StartBackgroundFileChecker(string file) 
{ 
    ListboxFile listboxFile = new ListboxFile(); 
    listboxFile.OnFileAddEvent += listboxFile_OnFileAddEvent; 
    BackgroundWorker backgroundWorker = new BackgroundWorker(); 
    backgroundWorker.WorkerReportsProgress = true; 
    backgroundWorker.DoWork += 
    (s3, e3) => 
    { 
     //check my file 
    }; 

    backgroundWorker.RunWorkerCompleted += backgroundWorker_RunWorkerCompleted; 
    backgroundWorker.RunWorkerAsync(); 
} 

void backgroundWorker_RunWorkerCompleted(object sender, RunWorkerCompletedEventArgs e) 
{ 
    if (Interlocked.Decrement(ref numWorkers) == 0) 
    { 
     //update my UI 
    } 
} 

, 많은 Wireshark 프로세스가 opned이 메모리에 많이 걸릴, 내 BackgroundWorker 완료 될 때까지 기다릴 수 및 다음 새 하나만 열 수 있습니까?

+0

확신 I 이 코드에 이미 주석을 달았습니다. 똑같은 충고, 작업자 내부에서 foreach 루프를 움직여 하나의 BGW 만 필요합니다. 스레드를 기다리는 것은 항상 나쁜 생각입니다. 코드가 교착 상태가됩니다. –

답변

8

를 첫 번째 요소를 가지고 업데이트 대신 foreach는이 같은, . 이 모든에있는 BackgroundWorker를 방지하고 단순히 파견을 통해 UI를 업데이트 할 수 있습니다 (최적이 아닌 수 있습니다 - 그렇다면,이 시도하여 백그라운드 스레드는 하나의 새로운 BackgroundWorker에 일을 시작합니다 해당 솔루션에서

//introduce additional field 
private AutoResetEvent _workerCompleted = new AutoResetEvent(false); 
//modify StartBackgroundFileChecker 
private void StartBackgroundFileChecker(string file) 
{ 
    ListboxFile listboxFile = new ListboxFile(); 
    listboxFile.OnFileAddEvent += listboxFile_OnFileAddEvent; 
    BackgroundWorker backgroundWorker = new BackgroundWorker(); 
    backgroundWorker.WorkerReportsProgress = true; 
    backgroundWorker.DoWork += 
    (s3, e3) => 
    { 
     //check my file 
    }; 

    backgroundWorker.RunWorkerCompleted += backgroundWorker_RunWorkerCompleted; 
    backgroundWorker.RunWorkerAsync(); 
    //new code - wait for completion 
    _workerCompleted.WaitOne(); 
} 
//add completion notification to backgroundWorker_RunWorkerCompleted 
void backgroundWorker_RunWorkerCompleted(object sender, RunWorkerCompletedEventArgs e) 
{ 
    if (Interlocked.Decrement(ref numWorkers) == 0) 
    { 
     //update my UI 
    } 

    //new code - notify about completion 
    _workerCompleted.Set(); 
} 

(System.Threading.AutoResetEvent 기준) in threadstart 대리인

내 생각에 병렬 스레드 수를 제어하고 여러 개의 제한된 수의 스레드에서 파일을 처리하는 것이 더 좋습니다.

private void btnAddDir_Click(object sender, EventArgs e) 
{ 
    var selectedPath = folderBrowserDialog1.SelectedPath; 
    Task.Factory.StartNew(() => 
     { 

      var files = Directory.EnumerateFiles(selectedPath, "*.*", SearchOption.AllDirectories); 

      Parallel.ForEach(files, 
          new ParallelOptions 
          { 
            MaxDegreeOfParallelism = 10 // limit number of parallel threads here 
          }, 
          file => 
          { 
           //process file here - launch your process 
          }); 
     }).ContinueWith(
      t => { /* when all files processed. Update your UI here */ } 
      ,TaskScheduler.FromCurrentSynchronizationContext() // to ContinueWith (update UI) from UI thread 
     ); 
} 

당신은 사용자의 특정 요구에이 솔루션을 조정할 수 있습니다

여기 (System.Threading.Tasks 네임 스페이스 기준) 대안 솔루션입니다.

사용되는 클래스/메소드 (참조 용 MSDN 참조)

  • Task
  • TaskScheduler.FromCurrentSynchronizationContext
  • Parallel.ForEach 방법 (는 IEnumerable, ParallelOptions, 액션)
+0

컨트롤의 병렬 번호가 훨씬 더 좋을 것이라고 생각합니다. – user2214609

0

어쩌면 파일의 목록을 유지하고 완료 후 그냥 당신이 번에 출시 단지 하나의 백그라운드 작업자를 원하는 알고있는 것처럼 당신의 목록

private List<string> _files; 

private void btnAddDir_Click(object sender, EventArgs e) 
{ 
    try 
    { 
     if (folderBrowserDialog1.ShowDialog() == DialogResult.OK) 
     { 

      _files = new List<string>(SafeFileEnumerator.EnumerateFiles(folderBrowserDialog1.SelectedPath, "*.*", SearchOption.AllDirectories)); 

      Interlocked.Increment(ref numWorkers); 
      var file = _files.FirstOrDefault(); 
      if(file != null) 
       StartBackgroundFileChecker(file); 
     } 
    } 
    catch (Exception) 
    { } 
} 

private void StartBackgroundFileChecker(string file) 
{ 
    ListboxFile listboxFile = new ListboxFile(); 
    listboxFile.OnFileAddEvent += listboxFile_OnFileAddEvent; 
    BackgroundWorker backgroundWorker = new BackgroundWorker(); 
    backgroundWorker.WorkerReportsProgress = true; 
    backgroundWorker.DoWork += 
    (s3, e3) => 
    { 
     //check my file 
    }; 

    backgroundWorker.RunWorkerCompleted += backgroundWorker_RunWorkerCompleted; 
    backgroundWorker.RunWorkerAsync(); 
} 

void backgroundWorker_RunWorkerCompleted(object sender, RunWorkerCompletedEventArgs e) 
{ 
    if (Interlocked.Decrement(ref numWorkers) == 0) 
    { 
     //update my UI 
     _files = _files.Skip(1); 
     var file = _files.FirstOrDefault(); 
     if(file != null) 
      StartBackgroundFileChecker(file); 
    } 
} 
+0

문제는 내가 "프로세스 중에"모든 파일을 가져 오기 위해 EnumerateFiles를 사용하고 있습니다. 모든 파일을 가져올 때까지 기다리지 않으려합니다. – user2214609

+0

문자열 목록으로 변환하여 모든 파일을 가져올 수 있습니다. 파일은 프로세스에 있지만, Backgroundworker가 완료된 후에 각 파일이 처리됩니다. 배경 노동자는 wireshark를 어디에서 열 수 있습니까? – jjchiw

+0

wireshark는 다른 클래스를 통해 프로세스를 엽니 다. // 내 파일을 확인합니다. – user2214609

관련 문제