await 和 async 阻塞 UI

Dar*_*dar 5 .net c# asynchronous winforms async-await

我写了一个小的 winforms 应用程序来搜索磁盘上的文件(就问题而言,哪个文件并不那么重要)。问题是它甚至可以是 100,000 个左右的文件。所以这个操作需要时间。

我想要实现的是将搜索操作作为异步操作进行,而不是阻塞 UI 线程,这样表单就不会卡住。

我可以用 backgroundWorker 做到这一点,但由于某种原因不能用 async\await 机制。

这是我的代码:

private async void button_FindFiles_Click(object sender, EventArgs e)
{
    await SearchFilesUtil.SearchPnrFilesAsync(this.textBox_mainDirectory.Text);
    MessageBox.Show("After SearchPnrFilesAsync");
}

public async static Task SearchPnrFilesAsync(string mainDir)
{
    foreach (string file in Directory.EnumerateFiles(mainDir, ".xml", SearchOption.AllDirectories))
    {
        var fileContenet = File.ReadAllText(file);
        var path = Path.Combine(@"C:\CopyFileHere", Path.GetFileName(file));
        using (StreamWriter sw = new StreamWriter(path))
        {
            await sw.WriteAsync(fileContenet);
        }
    }
}
Run Code Online (Sandbox Code Playgroud)

为什么 UI 线程卡住了而不MessageBox立即显示?我错过了什么?

And*_*yev 4

SearchPnrFilesAsync使用关键字本身进行标记的事实async并不会神奇地在单独的任务中异步启动此方法的执行。

事实上,SearchPnrFilesAsyncexcept中的所有代码都sw.WriteAsync在 UI 线程中执行,从而阻塞了它。

如果您需要在单独的任务中执行整个方法,您可以通过如下包装来完成:

public async static Task SearchPnrFilesAsync(string mainDir)
{
   await Task.Run(() => your_code_here);
}
Run Code Online (Sandbox Code Playgroud)

  • @dotctor为什么不呢,如果OP需要这个方法在另一个任务中完全运行的话?不仅您提到的“ReadAllText”同步运行,而且“Directory.EnumerateFiles”也同步运行。 (2认同)
  • [我应该公开同步方法的异步包装器吗?](http://blogs.msdn.com/b/pfxteam/archive/2012/03/24/10287244.aspx) (2认同)