Should I use async await on UI Thread or Task.Run

2019-07-24 03:26发布

问题:

I am writing an application in WPF using .NET 4.5. The application allows the user to select multiple files and import them. When this happens the application will parse text files and store the data into a database. The files can be very large so I want the UI to remain responsive and allow the user to do other things while this is happening.

I'm new to asynchronous programming and would to know what the best approach would be? According to a Microsoft article...

"The async and await keywords don't cause additional threads to be created. Async methods don't require multithreading because an async method doesn't run on its own thread. The method runs on the current synchronization context and uses time on the thread only when the method is active. You can use Task.Run to move CPU-bound work to a background thread, but a background thread doesn't help with a process that's just waiting for results to become available."

Since I am processing multiple files would I be better of using "Task.Run" for each file since they will run on separate threads? If not, what is the advantage of running everything on the same thread using async/await?

Note that no other UI operation (except progress bars - progress reporting) really cares about when these files are done processing so according to this article it seems like using Task.Run would benefit me. What are your thoughts?

回答1:

What are you doing with the files? If you're doing anything CPU intensive, it would be better to move that processing off the UI thread. If it's really just going to be the IO, then you can do it all in the UI thread - and still make it parallel.

For example:

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...
}

Here you're still doing all the actual processing on the UI thread - no separate threads are running, beyond potentially IO completion ports - but you're still starting multiple asynchronous IO operations at the same time.

Now one other thing to consider is that this might actually slow everything down anyway. If you're processing multiple files on the same physical disk, you might find that accessing them sequentially would be faster just due to the nature of disk IO. It will depend on the disk type though (SSDs would act differently to "regular" disks, for example).