I am writing a WinForms application 开发者_如何学Pythonin C# .NET and want to update the listview from the worker thread. I have read just about every post here on this but don't really fully understand the use of Invoke and delegates. In fact a few examples on here won't even compile as it complains of calling a non-static control from a static function.
I have a ListViewItem which I just want to pass to the UI thread via AddListItem(...). What is the best way to do this?
At present I have
this.lvcontrol.Invoke(new Action(() => lvcontrol.Items.Add(item)));
This is from MyForm::AddListView()
which is a static function. But of course the compiler complains that you can't call "this" or just "lvcontrol" from a static method. If the method isn't static I can't call the method from the static worker thread which is a member function of the Form.
You need a reference to the lvcontrol in order for the code to know which one you are trying to update (you could have two copies of the form open!).
If lvcontrol is a variable then drop the this at the begining eg
lvcontrol.Invoke(new Action(() => lvcontrol.Items.Add(item))
If it isn't your code is going to either all have to be non-static or you will need to pass a reference to the form around (and use that reference instead of the this, eg if frm is a reference to the form
frm.lvcontrol.Invoke(new Action(() => frm.lvcontrol.Items.Add(item))
Potentially, there are many troubles with static data in a multithreaded environment. For example, if one thread is iterating over the collection of items (in order to display the view), and another thread is modifying the collection, you will get an exception.
You probably need to review your code and remove static keyword from the multithreaded areas where you use reads and updates at the same time, plus add some data concurrency handling.
I would recommend some concurrent collection to which you DataBind to your ListView control. It is not a good idea to be passing around references to your form throughout the application.
My recommendation would be to use either the ConcurrentBag<T>
or ObservableCollection<T>
.
Give the worker thread a callback from the UI thread that the worker can use to pass the data for the ListView, and let the callback do the actual ListView update.
精彩评论