Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Thread runs slow when Invoke UI-Element

i am programming a benchmark tool, that reads a bunch of variables from a local server in a thread.

            int countReads = 1000;

            Int64 count = 0;

            for (int i = 0; i < countReads; i++)
            {
                Thread.CurrentThread.Priority = ThreadPriority.Highest;
                DateTime start = DateTime.Now;

                session.Read(null, 0, TimestampsToReturn.Neither, idCollection, out ReadResults, out diagnosticInfos);

                DateTime stop = DateTime.Now;
                Thread.CurrentThread.Priority = ThreadPriority.Normal;

                TimeSpan delay = (stop - start);

                double s = delay.TotalMilliseconds;
                count += (Int64)s;

                Dispatcher.Invoke(DispatcherPriority.Render, new Action(() =>
                {
                    progressBar1.Value = i;
                }));
            }

            double avg = (double)count / countReads;

            Dispatcher.Invoke(DispatcherPriority.Input, new Action(() =>
            {
                listBox1.Items.Add(avg);
            }));

I am calculating the timespan it took to proceed the read and getting the average timespan at the end.

            DateTime start = DateTime.Now;

            session.Read(null, 0, TimestampsToReturn.Neither, idCollection, out ReadResults, out diagnosticInfos);

            DateTime stop = DateTime.Now

if i run the code without updating the progressbar it took about 5ms average. but if i run it with

            Dispatcher.Invoke(DispatcherPriority.Render, new Action(() =>
            {
                progressBar1.Value = i;
            }));

it takes about 10 ms average.

My question is, why is the timespan higher when using the progressbar? i am just calculating the timespan for the read. Not including the progressbar update.

Is there any way to evacuate the ui-painting so that it doesn´t effect my read-timespan?

Thanks for your help.

Best regards

like image 878
Destructor Avatar asked Dec 16 '22 01:12

Destructor


1 Answers

Stop using Invoke to transfer progress information to the UI thread. Publish the progress information to a shared data structure or variable and have the UI thread poll for it using a timer on a reasonable interval. I know it seems like we have all been brainwashed into thinking Invoke is the be-all method for doing worker-to-UI thread interactions, but for simple progress information it can be (and often is) the worst method.

A polling method using a timer on the UI thread offers the following benefits.

  • It breaks the tight coupling that Invoke imposes on both the UI and worker threads.
  • The UI thread gets to dictate when and how often it should update the progress information instead of the other way around. When you stop and think about it this is how it should be anyway.
  • You get more throughput on both the UI and worker threads.

I know this does not directly answer your question as to why session.Read appears to run slower. Try changing your strategy for updating progress information from a push model (via Invoke) to a pull model (via a timer). See if that makes a difference. Even if it does not I would still stick with the pull model for the reasons listed above.

like image 83
Brian Gideon Avatar answered Mar 01 '23 13:03

Brian Gideon