ArtoAle
ArtoAle

Reputation: 2977

Refreshing a listview make program very slow

I'm new to C# and .NET programming and I'm trying to develop a windows TaskManager-like windows form application. I first populate the listView by using infos gathered from System.Diagnostics.Process, then I start a System.Threading.Timer with a MethodInvoker delegate who try to refresh listview data every seconds.

The problem is that the application is really slow, and, for sure, I'm doing something noobish.


public partial class Form1 : Form
    {
        private System.Threading.Timer t;
        private Process[] procVett;

        public Form1()
        {
            InitializeComponent();



        }

        private void Form1_Load(object sender, EventArgs e)
        {
            this.loadAppInfo(null);
            TimerCallback timerDelegate = new TimerCallback(this.refresh);
            this.t = new System.Threading.Timer(timerDelegate, null, 1000, 3000);
        }


        private void refresh(Object stateInfo)
        {
            procVett = Process.GetProcesses();

            this.BeginInvoke( (MethodInvoker)delegate
            {
                ListView.ListViewItemCollection ic = this.appList.Items;
                ListView.ListViewItemCollection procIc = this.procList.Items;
                time.Text = DateTime.Now.ToLongTimeString();
                int count = 0;
                procList.BeginUpdate();

                foreach (Process p in procVett)
                {

                    try
                    {
                        string cputime = p.TotalProcessorTime.TotalMinutes.ToString();

                        procIc[count].SubItems[1].Text = ("");
                        procIc[count].SubItems[2].Text = (cputime);
                        procIc[count].SubItems[3].Text =(p.WorkingSet64.ToString());
                        procIc[count].SubItems[4].Text = ("");

                    }
                    catch (System.Exception)
                    {

                    }

                    count++;
                }
                procList.EndUpdate();

            }, null);

        }
}

Upvotes: 0

Views: 2499

Answers (3)

Chris Doggett
Chris Doggett

Reputation: 20757

I'd suggest using VirtualMode on the ListView, which only displays the items currently in view. If you have 1,000,000 items, and it's only drawing #1,000-1020, it'll request those, you tell it how to get them from your item list in memory, and it draws them.

It's much faster than adding ListViewItems yourself, which is incredibly slow.

Here's a starter tutorial for it: Virtual Mode ListView

Also, I just started using ObjectListView this morning, and it's amazing.

Upvotes: 0

Alan McBee
Alan McBee

Reputation: 4320

You're basically on the right track, but I would avoid calling the BeginInvoke method until after you've looped through the processes in your array to collect the TotalProcessorTime time values.

Basically, the rule of thumb is to spend as little time on the UI thread as you can -- do as much work using background processes as you can.

Also, make sure you don't have threads or dispatches piling up in the thread pool. From the MSDN documentation for the Timer class:

If the SynchronizingObject property is a null reference (Nothing in Visual Basic), the Elapsed event is raised on a ThreadPool thread. If processing of the Elapsed event lasts longer than Interval, the event might be raised again on another ThreadPool thread. In this situation, the event handler should be reentrant.

So, watch for re-entrancy, and either ignore re-entrant timer events, or kill the processing on an older thread (using some thread-safe signaling mechanism).

Upvotes: 2

nxu
nxu

Reputation: 2272

Apart of what I said in comment:

I'd say create a separated collection of ListViewItems, parse process informations into that in a different thread (BackgroundWorker or simply anothery thread) and use that collection in your ListView after you finished updating it, that way the currently displayed list won't be frozen.

Upvotes: 1

Related Questions