1

I had an old winform app which used a performant plotting component (Mitov.PlotLab) in a timer like this:

private void updateGuiTimer_Tick(...)
{
    doSomeDemandingCalculations();
    plotTheResultsInComponent();
}

I did some refactoring and changed the code like this:

Task.Factory.StartNew(()=>
{
    while(isRunning)
    {
        doSomeDemandingCalculations();

        if(isPlotting) continue;

        isPlotting = true;
        BeginInvoke(new Action(()=>
        {
            plotTheResultsInComponent();
            isPlotting = false;
        }));
    }
}, TaskCreationOptions.LongRunning);

The problem is that the old approach could keep up with tick interval of 50 ms, and new code does just 20 percent of plotting compared to old one.

  • I replaced BeginInvoke with Invoke with no luck
  • I saw This and This which didn't help.
  • I replaced single continuous Task with repetitive Task launches and this made performance even worse.

Didn't I offload the computation from UI thread to another one and just did the plotting in UI thread? There where 3 timers in old code which did similar work. I refactored all of them to Tasks. Is there something wrong with my approach?

Community
  • 1
  • 1
Al Beir
  • 29
  • 2
  • Without a good [mcve] that reliably reproduces the problem (including both "before" and "after" behavior), it's impossible to say for sure what the issue might be. But it seems likely that you are flooding the UI thread with the `BeginInvoke()` calls, causing contention and slowdown. Please fix your question so that it has enough context to provide an actual answer. – Peter Duniho May 10 '17 at 06:21
  • You start BeginInvoke. While it calculates it's possible that you will have several calls to doSomeDemandingCalculations() because you call it before checking isPlotting – Leonid Malyshev May 10 '17 at 06:29
  • A timer and BeginInvoke use the same underlying mechanism. The latter is however a lot riskier, a great benefit you get from Timer is that it only ever ticks when the UI thread has nothing else to do. Ticking late when it is busy. You lost that benefit, now you have the risk of creating a *fire-hose* problem. Calling BeginInvoke() at a rate far higher than the timer used to tick before. That has consequences, like the UI thread spending too much time on painting. Simple to check, add Thread.Sleep(45) to slow it down. – Hans Passant May 10 '17 at 10:08

0 Answers0