简体   繁体   中英

Wait for Parallel Programming to Finish all tasks without freezing up GUI

I'm new to all the parallel programming paradigms in .NET and I'd like to know two things:

  1. How can I wait for all of my tasks to finish running without it freezing up my main form.
  2. Is my method of solving the following problem the best way to go about doing it?

I have a private async Task RunTask(string task) method that I need to run as many times as the number of tasks I have.

Inside a private async void button_click(object sender, EventArgs e) class, I have a List of strings called tasklist which initializes the tasks I need to run. I'm running the following code:

Thread thread = new Thread(()=> Parallel.ForEach(tasklist, t => RunTask(t)));
thread.Start();
RunOnCompletionOfTasks();

I need to be able to utilize all my CPU cores and run all tasks in the shortest amount of time possible. I figured Parallel.ForEach was the best way to achieve this but my tasks are also async because they have functions that require waiting on other methods. My tasks also append one string to a List<string> object within the class during their execution.

Parallel.ForEach causes my Windows Form to freeze up so I encapsulated it within a thread. The problem with this is that RunOnComlpetionOfTasks(); runs before my tasks have completed.

What's the most efficient way for me to run all my RunTask tasks and then run RunOnCompletionOfTasks upon completion without freezing up the Windows Form?

Please and thank you.

If you need to execute multiple Tasks (which are awaitable) then Parallel.ForEach may not be the best choice. It is truly designed for CPU bound processes and does not support async operations.

You may try to rewrite your code using Task.WhenAll() :

var tasks = tasklist.Select(RunTask);
// assuming RunTask is declared as `async Task`
await Task.WhenAll(tasks);

This way your are leveraging the use of async / await pattern inside your method call.

If, instead, you realize that your tasks are not properly async (and are only CPU bound) you may try to execute Parallel.ForEach inside a simple Task

await Task.Run(() => Parallel.ForEach(tasklist, RunTask);
// assuming RunTask is not `async Task`

First off all you need to distinguish parallel and asynchronous:

  1. When you need to do something with IO asynchronous is usually play.

  2. When you need to do something with computing (like archiving files or image processing) is parallel stuff is usually coming play.

async await pattern its just a shortcut and its not silver bullet.

If You need just to parallel your computation I suggest to use parallel staff from TPL like ParallelForEach, they a playing cool and optimized very good to get maximum performance.

If you are trying to perform some IO operations this can make sense but on more or less huge processing data amount - like server app.

Your processor can't do more then it can

Any parallel staff sill not help you if your task is not parallel. Be aware of any context switch has some cost. TaskSheduler will use queue to decrease threads count but its doing some work again.

Thread new Thread is evil (here at least). Your processor will be switched to one more thread more frequently (more threads - more switches)

Finally: Try not yo use TPL things when you are not aware how does things work. Just use classes you need and dont do optimization that dont really optimize.

PS Use ContinueWith in UI. Anything in TPT will return task that has this method, Updating UI be sure of thread you are currently in.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM