Search code examples
c#.netwpfbackgroundworker

Performance issue on BackgroundWorker in C#


I have a strange problem with BackgroundWorker preformance in C#. I have an application that among other things use a BackgroundWorker to execute certain task. Basicaly the task is the following:

public void simulate(Image imgSimulator)
        {
            simulador = new Simulator(imgSimulator);
            simulador.setBackground(0);
            Constants.finishSimulation = false;
            BackgroundWorker bw = new BackgroundWorker();
            bw.DoWork += run;
            bw.RunWorkerAsync(imgSimulator);
        }

public void run(object sender, DoWorkEventArgs e)
        {
            Image imgSimulator = (Image)e.Argument;
            bool clear;
            foreach (Program p in programs)
            {
                Resource r = p.getResource(0);
                clear = true;
                if (r is Text)
                {
                    Text t = (Text)r;
                    clear = t.getClearPrev() == 1;
                }
                if (!clear)
                {
                    simulador.setBackground(FontBitmap.COLOR_BLACK);
                }
                p.execute(simulador, imgSimulator);
                if (Constants.finishSimulation)
                {
                    break;
                }
            }

        }

The principal function in the code above is execute:

public void execute(Simulator simulador, System.Windows.Controls.Image imgSimulator)
        {
            long now = DateTime.Now.Ticks / 10000;
            long current = DateTime.Now.Ticks / 10000;
            while (true)
            {
                current = DateTime.Now.Ticks / 10000;
                if (current - now >= 1)
                {
                    App.Current.Dispatcher.Invoke((Action)(() =>
                    {
                        ((MainWindow)System.Windows.Application.Current.MainWindow).Title = "" + Constants.index++;

                    }));
                    now = DateTime.Now.Ticks / 10000;
                }
            }
        }

I have modified execute function to debug purpose, now it change the main window title.

The problem is that in my pc the app runs correctly, but I tried it in another pc and the title doesn't update at the same speed rate.

Here are some data (the only thing that I have changed to do this tests is the number 10000)

If I change 10000 to 1000000 in my pc the app takes 30 second to reach 300 (in the window title bar), and the same happen in the other pc. If I change 10000 to 100000 in my pc the app takes 30 second to reach 3000 (in the window title bar), but in the another pc it takes 47 second to reach 3000

Other thing that I noted is that if I open another C# app (WPF) and I pass the mouse over their controls (or focus a TextBox) the app runs correctly (at the same speed rate that it runs in my pc).

The only difference among my pc and the other is that I have Visual Studio 2013 installed.

What could be the problem?

Thanks.


Solution

  •    if (current - now >= 1)
    

    This does not do what you hope it does, DateTime.Now does not update every single millisecond. By default, it gets updated 64 times per second, once every 15.625 msec. So your Constants.index cannot be increment by more than 64 per second.

    But other processes and drivers can change that update rate by calling timeBeginPeriod(). A browser is apt to change it to 10 msec for example, a happy number to animate gifs. Now you'll increment Constants.index a hundred times per second.

    Which is exactly what you see: 15.625 / 10 * 30 sec = 47 sec.

    You can see the active rate on a machine by running powercfg /energy from an elevated command prompt. The generated report shows the number under the heading "Platform Timer Resolution".

    You must avoid taking a dependency on the update rate.