2015-12-14 64 views
-1

我有一個程序用於搜索給定的目錄並將所有文件添加到列表視圖。我的問題是,當搜索繁忙時,UI線程卡住了。我嘗試過使用任務,但無法讓它在異步中工作。列表視圖必須在找到每個文件後更新。Winforms遞歸文件掃描塊UI

我對TPL以及如何使用它做了大量的閱讀,但在這種情況下無法使用它。我將它用於處理數據的一種方法,即創建一個任務來處理它。任何人都可以告訴我下面的代碼有什麼問題,以及如何解決它?

這裏是我的代碼:

private void button1_Click(object sender, EventArgs e) 
{ 
    Task.Run(() => 
    { 
     WalkDirectory(new DirectoryInfo(drive)); 
    }); 
} 

public void testTaskUpdateLabel(string labelTeks) 
{ 
    Task taskUpdateLabel = new Task(() => 
    { 
     label4.Text = labelTeks; 
    }); 
    taskUpdateLabel.Start(uiScheduler); 
} 

public void testTaskUpdateLabel(string labelTeks) 
{ 
    Task taskUpdateLabel = new Task(() => 
    { 
     label4.Text = labelTeks; 
    }); 
    taskUpdateLabel.Start(uiScheduler); 
} 

public bool WalkDirectory(DirectoryInfo directory) 
{ 
    if (directory == null) 
    { 
     throw new ArgumentNullException("directory"); 
    } 
    return this.WalkDirectories(directory); 
} 

private bool WalkDirectories(DirectoryInfo directory) 
{ 
    bool continueScan = true; 
    continueScan = WalkFilesInDirectory(directory); 

    if (continueScan) 
    { 
      DirectoryInfo[] subDirectories = directory.GetDirectories(); 

      foreach (DirectoryInfo subDirectory in subDirectories) 
      { 
       try 
       { 
        if ((subDirectory.Attributes & FileAttributes.ReparsePoint) != 0) 
        { 
         continue; 
        } 
        if (!(continueScan = WalkDirectory(subDirectory))) 
        { 
         break; 
        } 
       } 
       catch (UnauthorizedAccessException) 
       { 
        continue; 
       } 
      } 
    } 
    if (continueScan) 
    { 
     testTaskUpdateLabel(directory.FullName); 
    } 
    return continueScan; 
} 

private bool WalkFilesInDirectory(DirectoryInfo directory) 
{ 
    bool continueScan = true; 
    // Break up the search pattern in separate patterns 
    string[] searchPatterns = _searchPattern.Split(';'); 

    // Try to find files for each search pattern 
    foreach (string searchPattern in searchPatterns) 
    { 
     if (!continueScan) 
     { 
      break; 
     } 
     // Scan all files in the current path 
     foreach (FileInfo file in directory.GetFiles(searchPattern)) 
     { 
      try 
      { 
       testTaskUpdate(file.FullName); 
      } 
      catch (UnauthorizedAccessException) 
      { 
       continue; 
      } 
     } 
    } 
    return continueScan;   

}

回答

0

我通過使walkDirectory,walkDirectories和WalkFiles方法異步來得到它的工作。因此,在調用testUpdate和testUpdateLabel方法之前使用await關鍵字。這樣,在搜索運行時不會阻塞UI線程的情況下,使用搜索結果更新列表視圖。 I.E.用戶可以在找到他正在搜索的文件時取消搜索。

3

如果你使用一個BackgroundWorker類,用戶界面將工作和進步可以在ProgressChanged事件處理程序進行更新。

MSDN Reference

0

可以在任何一個電話我什麼是錯在下面的代碼,以及如何解決它?

的問題是在這裏

public void testTaskUpdateLabel(string labelTeks) 
{ 
    Task taskUpdateLabel = new Task(() => 
    { 
     label4.Text = labelTeks; 
    }); 
    taskUpdateLabel.Start(uiScheduler); 
} 

你不應該使用TPL更新UI。 TPL任務用於執行非UI工作,UI只應在UI線程上更新。您已將工作移至線程池線程(通過Task.Run),因此您唯一需要解決的問題是如何從工作人員內部更新UI。有很多方法可以做到這一點 - 使用Control.Invoke/BeginInvoke,SynchronizationContext等,但TPL的首選方法是通過並使用IProgress<T>接口。不要被名字所迷惑 - 界面是一些數據的回調抽象。有一個標準的BCL提供的實現 - Progress<T>類有以下行爲,根據

提供與ProgressChanged事件註冊的構造函數或事件處理程序的任何處理,通過拍攝的的SynchronizationContext實例調用時,實例文檔

建。

即完全符合UI更新場景。

儘管如此,以下是如何將它應用於您的代碼。我們將使用IProgress<string>,並且會撥打Report方法,併爲我們找到的每個文件/目錄傳遞全名 - 直接替換您的testTaskUpdateLabel調用。

private void button1_Click(object sender, EventArgs e) 
{ 
    var progress = new Progress<string>(text => label4.Text = text); 
    Task.Run(() => 
    { 
     WalkDirectory(new DirectoryInfo(drive), progress); 
    }); 
} 

public bool WalkDirectory(DirectoryInfo directory, IProgress<string> progress) 
{ 
    if (directory == null) throw new ArgumentNullException("directory"); 
    if (progress == null) throw new ArgumentNullException("progress"); 
    return WalkDirectories(directory, progress); 
} 

bool WalkDirectories(DirectoryInfo directory, IProgress<string> progress) 
{ 
    // ... 
    if (!(continueScan = WalkDirectories(subDirectory, progress))) 
    // ... 
    if (continueScan) 
     progress.Report(directory.FullName); 
    // ... 
} 

bool WalkFilesInDirectory(DirectoryInfo directory, IProgress<string> progress) 
{ 
    // ... 
    try 
    { 
     progress.Report(file.FullName); 
    } 
    // ... 
} 
+0

這stil阻止ui線程。 E.G用戶不能在搜索對話框中選擇calsel,直到搜索操作完成。這就是爲什麼我嘗試使用在當前ui上下文上運行的seprid任務 – Hendri

+0

這不可能是真實的,至少是顯示的代碼。整個過程都在單獨的線程上,所以你的UI線程應該是免費的,除非你正在做其他事情並阻止它。 –

+0

好吧。我沒有做任何在我的問題中沒有顯示的代碼。 – Hendri