我在C#.NET中编写WinForms应用程序,并希望从工作线程更新listview。我已经阅读了关于此的每篇文章,但并不完全理解Invoke和委托的使用。事实上,这里的一些例子甚至都不会编译,因为它抱怨从静态函数调用非静态控件。
我有一个ListViewItem,我只想通过AddListItem(...)传递给UI线程。这样做的最佳方式是什么?
目前我有
this.lvcontrol.Invoke(new Action(() => lvcontrol.Items.Add(item)));
这是来自MyForm::AddListView()
这是一个静态函数。但是当然编译器抱怨你不能从静态方法调用“this”或“lvcontrol”。如果方法不是静态的,我不能从作为Form的成员函数的静态工作线程调用该方法。
答案 0 :(得分:2)
您需要对lvcontrol的引用,以便代码知道您要更新哪一个(您可以打开表单的两个副本!)。
如果lvcontrol是一个变量,那么将其放在开头的那个例如
lvcontrol.Invoke(new Action(() => lvcontrol.Items.Add(item))
如果不是你的代码要么全部必须是非静态的,要么你需要传递对表单的引用(并使用该引用而不是this,例如,如果frm是对表格
frm.lvcontrol.Invoke(new Action(() => frm.lvcontrol.Items.Add(item))
答案 1 :(得分:0)
在多线程环境中,静态数据可能存在许多问题。例如,如果一个线程正在遍历项集合(为了显示视图),而另一个线程正在修改集合,则会出现异常。
您可能需要检查代码并从同时使用读取和更新的多线程区域中删除静态关键字,并添加一些数据concurrency handling。
答案 2 :(得分:0)
我建议你concurrent collection控制一些DataBind to your ListView。在整个应用程序中传递对表单的引用并不是一个好主意。
我的建议是使用ConcurrentBag<T>
或ObservableCollection<T>
。
答案 3 :(得分:0)
为工作线程提供一个来自UI线程的回调,工作者可以使用它来传递ListView的数据,并让回调执行实际的ListView更新。