我应该在UI Thread或Task.Run上使用async await来处理多个文件吗?

时间:2013-03-02 22:58:10

标签: wpf multithreading asynchronous async-await .net-4.5

我正在使用.NET 4.5在WPF中编写应用程序。该应用程序允许用户选择多个文件并导入它们。发生这种情况时,应用程序将解析文本文件并将数据存储到数据库中。文件可能非常大,所以我希望UI保持响应,并允许用户在发生这种情况时做其他事情。

我是异步编程的新手,想知道最好的方法是什么?根据{{​​3}} ...

  

“async和await关键字不会导致创建其他线程。异步方法不需要多线程,因为异步方法不能在自己的线程上运行。该方法在当前同步上下文中运行并使用时间只有在方法处于活动状态时,才能在线程上使用。您可以使用Task.Run将CPU绑定的工作移动到后台线程,但后台线程无法帮助只等待结果可用的进程。“

由于我处理多个文件,我会更好地为每个文件使用“Task.Run”,因为它们将在不同的线程上运行?如果没有,使用async / await在同一个线程上运行所有内容有什么好处?

请注意,没有其他UI操作(进度条除外 - 进度报告)真正关心这些文件何时完成处理,因此根据本文,似乎使用Task.Run会让我受益。你的想法是什么?

1 个答案:

答案 0 :(得分:3)

你在做什么文件?如果您正在执行任何CPU密集型操作,那么最好将该处理移出UI线程。如果它真的只是IO,那么你可以在UI线程中完成所有操作 - 仍然使它并行。

例如:

private async Task ProcessAllFiles(IEnumerable<string> files)
{
    List<Task> tasks = files.Select(x => ProcessFile(x))
                            .ToList();
    await Task.WhenAll(tasks);
    textBox.Text = "Finished!";
}

private async Task ProcessFile(string file)
{
    // Do stuff here with async IO, and update the UI if you want to...
}

在这里,您仍然在UI线程上进行所有实际处理 - 没有单独的线程正在运行,超出了潜在的IO完成端口 - 但您仍然在同时启动多个异步IO操作。

现在需要考虑的另一件事是,这个可能实际上减慢了一切。如果您在同一物理磁盘上处理多个文件,您可能会发现,由于磁盘IO的性质,按顺序访问它们会更快。这取决于磁盘类型(例如,SSD对“常规”磁盘的行为不同)。