Update ListView from a thread not the original thread in C#

2.1k Views Asked by At

I already know that to update control, I can use Invoke Action

progressBar1.Invoke(new Action(() => { progressBar1.Maximum = 0; }));

But that only work with property of control which are single data. Now I have a thread that need to change the list view collection of list view items, clear it then update with new items, new texts and icon images. What is the different between them, an integer or a bool compare to a list, array or a collection of integer, bool or even component, control. Can I just simple add

string[] newItemText = {"item1", "item2", ...};
listView1.Invoke(new Action() => {
    i = 0;
    foreach(var item in listView1.Items)
    {
         item.Text = newItemText[i];
         i++; 
    }
}));

I may need a solution for my list view but if you have an answer, please explain clearly why and how it work, cause I need to learn thoroughly about it. Also you can notice me about the risk when trying that practice.

EDIT: The question is not about how to update control from other thread. IT about when and why need to do this and not to to that. Moreover, I need to know the different between update a single data and update the whole collection of data.

1

There are 1 best solutions below

7
On BEST ANSWER

There is no difference in updating a value or adding more elements to a list.

What internally happens is that the graphic resources being used to draw in Windows (it can also be applied to Android) it requires the usages of Pens, Brushes, and those type of objects.

Those objects belong to the context of the thread in which they have been instantiated originally. This typically happens in the main thread, but if you would create the graphical object, in this case the List, in a separate thread different that the main, that specific thread would be the "owner" thread of your control.

If you want to change something in the Control which requires refreshing the UI (requires the usages of Pens, Brushes, etc.) you have to do that from the same thread which "owns" your Control. That's why you need to use Invoke.

That's the main principle. If you update a scalar value as Integer, or if you add elements to a list, there is no difference. Both require the usage of graphical resources, so both require being called from the same thread that owns the Control.

Let me know if it is clear.

Edit. In any case your code looks a bit strange, because you are filling the List iterating from the own list. Wouldn't make more sense to do this?:

string[] newItemText = {"item1", "item2", ...};
listView1.Invoke(new Action() => {
   for(int i = 0; i < newItemText.length; i++)
   {
     listView1.add(newItemText[i]);
   }
});

without knowing the rest of the context, it sounds more logical to me.