問題描述
如何在不阻塞的情況下用大量信息填充列表視圖? (How to populate listview with a lot of information without blocking?)
I am creating an array of ListViewItems on a background thread and then i populate my listview with it on the ui thread. The problem is that if the array is too big the ui blocks while the listview is updated.
Is there a way to populate the listview with a small impact on the ui?
‑‑‑‑‑
參考解法
方法 1:
If you have a lot of data going into it you might want to use it in virtual mode, by setting the VirtualMode
property of the ListView control to true
. That means that the ListView will not be populated in the traditional sense, but you will hook up event handlers where you deliver the information to the list view in small chunks as the items are being displayed.
Very simple example:
private List<string> _listViewData = new List<string>();
private void toolStripButton1_Click(object sender, EventArgs e)
{
_listViewData = GetData(); // fetch the data that will show in the list view
listView1.VirtualListSize = _listViewData.Count; // set the list size
}
// event handler for the RetrieveVirtualItem event
private void listView_RetrieveVirtualItem(object sender, RetrieveVirtualItemEventArgs e)
{
if (e.ItemIndex >= 0 && e.ItemIndex < _listViewData.Count)
{
e.Item = new ListViewItem(_listViewData[e.ItemIndex]);
}
}
You should also look into using the CacheVirtualItems
event.
方法 2:
You can also use BeginUpdate and EndUPdate methods
listView1.BeginUpdate();
//Add Values
listView1.EndUpdate();
方法 3:
My comments got quite long, so I decided to make this a separate post.
First, +1 for Fredrik Mörk, using VirtualMode
is the way to go. However, you do lose some functionality, e.g. column autosize, and sorting is easier handled on your own.
If that is a problem, populating from a worker thread may sound sounds tempting. However, the population will still take place in the thread that owns the list control (i.e. virtually always the main thread) ‑ .NET makes that visible by enforcing you to use (Begin)Invoke
. Additionally, the context switches will notably increase the total time you need to fill all items if you fill one by one, so you want to fill in chunks (say 50 items at a time, or even better fill as many as you can in 20 milliseconds). Add to that the additional synchronization required when contents changes, you have a quite complex solution for a not‑so‑stellar result.
(by Elz、Fredrik Mörk、Ahmed、peterchen)