0

I have a progress bar on the front-end of my web app which gets its current percentage by listening for messages sent from a SignalR hub in the back-end. It tracks a long running process which has several stages with many iterations.

My initial set-up was to simply send a message every iteration. This caused issues however as the rate of iteration (and therefore message rate) was too fast for the front-end and the bar became very jumpy and buggy.

So instead I decided to use a Stopwatch object in the following way (where SendProgress() is the procedure that tells the hub to message the client):

int progressCount = 1;
var stopWatch = new System.Diagnostics.Stopwatch();
stopWatch.Start();

for(int i=0; i<taskCount; i++)
{

    //PROCESS DONE HERE

    if (stopWatch.Elapsed.TotalMilliseconds >= 500.0)
        {
            SendProgress(taskCount, progressCount, 0, 40);
            stopWatch.Reset();
            stopWatch.Start();
        }
        progressCount++;
}

Thus preventing messages from being sent faster than once every 500ms.

This worked well in terms of limiting the message rate, however I noticed a drop in performance, which after a little research I gather is due to using Stopwatch, which is inefficient.

What would be a better approach here? I also though of using Thread.Sleep() but that would just be adding artificial slowness to the algorithm which is, obviously, bad. Is there a way I can accurately control the message rate, without slowing things down too badly?

1 Answer 1

1

Run this in a console app to see if the logic applies to what you want to do. Check the comments to track what's happening (and let me know if you need me to break it down further). Happy coding! ;)

static void Main(string[] args)
{
    //set the percentage you want to show progress for (eg, every 20%).
    const int updatePercentage = 20;
    //this is just the total of the for loop for this example.
    const int loopMax = 1000000;
    //calculate what 20% of the total is, to set as the check point used to show the progress.
    decimal loopCheck = Convert.ToDecimal(loopMax * (Convert.ToDecimal(updatePercentage) / 100));

    for (int i = 1; i <= loopMax; i++)
    {
        //check if the mod of the current position meets the check point. 
        if ((i % loopCheck) == 0)
        {
            //show the progress...
            Console.WriteLine($"You've reached the next {updatePercentage}% of the for loop ({i.ToString("#,##0")})");
        }
    }
    Console.ReadLine();
}
Sign up to request clarification or add additional context in comments.

1 Comment

updatePercentage should be calculated from loopMax. Otherwise, if there are many tasks, it might look strange if the percentage jumps by 20% increments and then nothing happens for several seconds.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.