我正在 C# .NET 中编写 WinForms 应用程序,并希望从工作线程更新列表视图。我已经阅读了这里的几乎每一篇文章,但并没有真正完全理解 Invoke 和委托的使用。事实上,这里的一些示例甚至无法编译,因为它抱怨从静态函数调用非静态控件。
我有一个 ListViewItem,我只想通过 AddListItem(...) 将其传递到 UI 线程。最好的方法是什么?
目前我有
this.lvcontrol.Invoke(new Action(() => lvcontrol.Items.Add(item)));
This is from MyForm::AddListView() 这是一个静态函数。但编译器当然会抱怨你不能从静态方法调用“this”或只是“lvcontrol”。如果该方法不是静态的,我无法从作为表单成员函数的静态工作线程调用该方法。
I am writing a WinForms application in 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.
发布评论
评论(4)
您需要对 lvcontrol 的引用,以便代码知道您正在尝试更新哪一个(您可以打开表单的两个副本!)。
如果 lvcontrol 是一个变量,那么在开头删除 this 例如,
如果不是,您的代码要么全部必须是非静态的,要么您需要传递对表单的引用(并使用该引用而不是this,例如,如果 frm 是对表单的引用
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
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
在多线程环境中,静态数据可能会带来很多问题。例如,如果一个线程正在迭代项目集合(为了显示视图),而另一个线程正在修改该集合,您将收到异常。
您可能需要检查代码并从同时使用读取和更新的多线程区域中删除 static 关键字,并添加一些数据 并发处理。
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.
我会推荐一些并发集合,您DataBind 到您的 ListView 控件。在整个应用程序中传递对表单的引用并不是一个好主意。
我的建议是使用
ConcurrentBag
或ObservableCollection
。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>
orObservableCollection<T>
.为工作线程提供来自 UI 线程的回调,工作线程可以使用该回调来传递 ListView 的数据,并让回调执行实际的 ListView 更新。
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.