Ali Tor
Ali Tor

Reputation: 2945

Listview update in ProgressChanged event slows down the application too much

I have a ProgressChanged event for download and in this event I update a Listview writing async threads statuses. But this operation slows down the program, even causes Not Responding. My code and an ss are below. How can I fix this problem.

private void downloader_ProgressChanged(object sender, EventArguments.ProgressChangedEventArgs e)
{
    this.Invoke(new Action(() =>
    {
        progressBar1.Value = (int)(downloader.Progress * 100);
        if (downloader.Info.ContentSize > 0)
            lblContentSize.Text = downloader.Info.ContentSize.ToHumanReadableSize();
        lblSpeed.Text = downloader.Speed.ToHumanReadableSize() + "/s";
        lblReceived.Text =
            string.Format("{0} ({1})",
                downloader.TotalBytesReceived.ToHumanReadableSize(),
                string.Format("{0:0.00}%", downloader.Progress));
        segmentedProgressBar1.ContentLength = downloader.Info.ContentSize;
        segmentedProgressBar1.Bars = downloader.Ranges.ToList().Select(x => new Bar(x.TotalBytesReceived, x.Start, x.Status)).ToArray();
        lblResumeability.Text = downloader.Info.AcceptRanges ? "Yes" : "No";
        listView1.BeginUpdate();
        writeThreads();
        listView1.EndUpdate();
    }));
}

private void writeThreads()
{
    var ranges = downloader.Ranges.ToList();
    ranges = ranges.Where(x => !x.IsIdle).ToList();
    for (var i = 0; i < ranges.Count; i++)
    {
        listView1.Items[i].SubItems[1].Text = (ranges[i].TotalBytesReceived.ToHumanReadableSize());
        listView1.Items[i].SubItems[2].Text = (ranges[i].Status.ToString());
    }
}

enter image description here

Upvotes: 2

Views: 58

Answers (1)

aepot
aepot

Reputation: 4824

DownloadProgressChanged being fired on every chunk received e.g. for each 4kb received. You probably may update UI not for each call but only if percentage was changed.

private int storedPercentage = -1;

private void downloader_ProgressChanged(object sender, EventArguments.ProgressChangedEventArgs e)
{
    if (e.ProgressPercentage != storedPercentage)
    {
        storedPercentage = e.ProgressPercentage;
        this.Invoke((Action)(() =>
        {
            // existing code...
        }));
    }
}

Disclamer: exactly this way to fix is applicable only for single active download process. But the idea would be the same for concurrent downloads.

Upvotes: 1

Related Questions