r wank
r wank

Reputation: 352

Multithreading a GUI using backgroundworkers

There is 2 Backgroundworkers in my project:

BGW1: the first worker is used to read data from a controller and convert the data into the right format

BGW2: the second worker is used to pass the converted data and objects to the GUI using the ReportProgress functionality

The entire process needs to be as real time as possible and the messages are coming approx every 0.5 ms. The MainThread becomes flustered pretty quick when it has to update 800 points every 5-10 ms.

This causes the GUI to become unresponsive if i update at a faster rate than 10fps.

A solution i have found online, is this: Alternate Way of Multithreaded GUI

I have tryed to adopt this methodology to my background workers by setting

        // Prevent the framework from checking what thread the GUI is updated from.
        theMainForm.CheckForIllegalCrossThreadCalls = false;

in the main form. This allows me to update the gui from a seperate thread not the main thread, from what i understand. Using this line in the main should mean that i can access the GUI elements from other threads that arent the main thread, and i dont need to use ReportProgress to update the Chart, so i tried updating the Chart from my DoWork portion of BGW2.

The update works from DoWork, but it seems to still just refer the Data to the MainThread and that thread then updates the chart, which results in an unusable GUI again.

Do i have to get rid of the backgroundworkers completly and only use Threads for the solution from the link to work? Or is there some sort of trick to getting this method to work with backgroundworkers.

Upvotes: 0

Views: 80

Answers (3)

Binkan Salaryman
Binkan Salaryman

Reputation: 3058

Have you tried to enforce the events being handled? This will empty the events queue so the form becomes responsible for the user. Nevertheless you better go with updating the GUI at a fixed rate, as pointed out by Luaan.

Upvotes: 0

Gusdor
Gusdor

Reputation: 14332

One background worker really is enough.

The expensive parts of this operation are;

  1. Synchronizing back to the UI thread
  2. Blocking the worker while you do it.

The solve the performance issue, minimise #1. Don't post every item, post many items every x milliseconds.

In fact, I'd recommend not using a background worker at all - the ReportProgress event blocks your worker thread.

Upvotes: 0

Luaan
Luaan

Reputation: 63772

Well, don't update that often. Just stick to a fixed refresh rate, and use a ConcurrentQueue to pass the data points between the BackgroundWorker that reads the data, and the GUI that renders it. A simple Timer should work well enough - every five seconds, read everything out of the ConcurrentQueue and update the chart.

Don't update the UI from multiple threads. There's a reason why the checks are there.

Upvotes: 2

Related Questions