Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Can I use multiple BackgroundWorker's in a synchronous way in WPF?

In my WPF application - I have a Listview with a Gridview inside. A user is able to add files to this list.

The gridview should allow me to have quite rich "rows", each row showing file name, extra application detail and most importantly a progress bar. Each row in the gridview is databound to a business object in a collection, and specifically the object has a property "Progress" which is bound to the progress bar.

I need to process each file, extract data and send the data to a web service and I would like to display the progress for each file in it's respective progress bar as I work through the collection of files.

Initially I started off with a simple loop containing the processing logic which periodically updated the "Progress" field for each row and noted that the UI didn't update very well.

I then moved the processing logic in the loop to a BackgroundWorker which modified the business object "Progress" field, and because the UI thread was not working so hard - it was a lot more responsive.

However due to the asynchronous nature of BackgroundWorker, it started multiple BackgroundWorkers (one for each row) virtually all at once as the loop spun out. All my progress bars started progressing...

What would be the best approach to limit it to only 2-3 BackgroundWorkers going at once? Or even leave it at one BackgroundWorker - and it doesn't start until the previous one is completed? How can I introduce a dependency so that in essence all the BackgroundWorkers are synchronous?

like image 729
dan Avatar asked Jan 20 '23 15:01

dan


2 Answers

You can use the Task class for that, like in sample here

like image 171
oleksii Avatar answered Jan 30 '23 07:01

oleksii


If you really want only one to execute at the same time, then there are several approaches. You can use the Task class and a TaskScheduler like @oleksii suggested in his answer or you can post work elements to a Queue and have a background thread work one them one after the other.

But if all you want is to do the work in the most optimal way depending on the current hardware your program is running on then I'd say leave it to the default task scheduler. Just call StartNew on the TaskFactory whenever you want to do work for a grid row and leave scheduling to .NET.

If you do have dependencies between tasks, you can use one of the ContinueWith overloads to maintain order between jobs.

like image 43
Isak Savo Avatar answered Jan 30 '23 07:01

Isak Savo