Home > Mobile >  Proper way to update label with progress from a different thread
Proper way to update label with progress from a different thread

Time:10-04

I have a windows form program. In the main form I have a label where I update with progress. I use the following code to perform my operations:

Thread workThread = new Thread(delegate ()
{
    for (int i = 1; i < bytes.Length; i  )
    {
        SliderOverBytesAndDoProcessing();
    }
});

workThread.Start();

The function SliderOverBytesAndDoProcessing() performs operations where I read 4 bytes and perform some operations on more bytes. I do this for each 4 bytes of the 200MB file (read 4 bytes process something and continue moving). Everything works fine until I decide to report my progress. Here is how I do the update:

Thread workThread = new Thread(delegate ()
{
    for (int i = 1; i < bytes.Length; i  )
    {
        Lbl.Invoke((Action)delegate { Lbl.Text = "Processing "   (ii / 1048576)   "/"   (bytes.Length / 1048576); }
        SliderOverBytesAndDoProcessing();
    }
});

workThread.Start();

If I add that one line the program becomes too slow. I mean the program runs in around a few minutes without that line but with that line it takes around 1.5 hours. Also, on some other operations if I do that, I end up in infinite loops. How do I report my progress from the other thread to form thread without facing this problem.

Thanks.

CodePudding user response:

It is slow because you’re dispatching to the UI thread on every byte, even though the progress message only seems to care about megabytes. So you change the label over a million times to the same value.

Consider

var totalMb = bytes.Length / 1024 / 1024;
var lastMb = -1;

for (int i = 1; i < bytes.Length; i  ) {
  var currentMb = i / 1024 / 1924;
  if (currentMb > lastMb) {
    Lbl.Invoke(() => { Lbl.Text = $"Processing {currentMb}/{totalMb} MiB" });
    lastMb = currentMb;
  }
  SliderOverBytesAndDoProcessing();
}
  • Related