我想从表单中的 BackgroundWorker
获取控件的属性:
foreach (ListViewItem i in ListView.CheckedItems) { //error: Cross-thread operation not valid: Control 'ListView' accessed from a thread other than the thread it was created on.
//do something with i
}
谁能推荐最简单的方法来做到这一点?
最佳答案
让我再试一次......
1.) 将 ListView 拖到窗体上
2.) 将 BackgroundWorker 拖到窗体上
3.) 创建一个方法来遍历 ListViewItem 集合
private void LoopThroughListItems()
{
foreach (ListViewItem i in listView1.CheckedItems)
DoSomething();
}
4.) 添加代码以在 BackgroundWorker 的 DoWork 事件中调用 LoopThroughListItems()
private void backgroundWorker1_DoWork(object sender, DoWorkEventArgs e)
{
LoopThroughListItems();
}
5.) 在您的表单加载中 - 在主线程上执行代码(有效),然后在 backgroundWorkder 线程上执行(失败)
private void Form1_Load(object sender, EventArgs e)
{
// Try it on the UI Thread - It works
LoopThroughListItems();
// Try it on a Background Thread - It fails
backgroundWorker1.RunWorkerAsync();
}
6.) 修改您的代码以使用 IsInvokeRequired/Invoke
private void LoopThroughListItems()
{
// InvokeRequired == True when executed by non-UI thread
if (listView1.InvokeRequired)
{
// This will re-call LoopThroughListItems - on the UI Thread
listView1.Invoke(new Action(LoopThroughListItems));
return;
}
foreach (ListViewItem i in listView1.CheckedItems)
DoSomething();
}
7.) 再次运行应用程序 - 现在它可以在 UI 线程和非 UI 线程上运行。
那就解决问题了。检查 IsInvokeRequired/Invoking 是一种您会经常使用的常见模式(这就是它包含在所有控件中的原因)。如果你到处都在做,你可以做一些聪明的事情并将它全部包起来 - 如下所述:Automating the InvokeRequired code pattern
关于c# - 从另一个线程获取控件的属性,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/10571949/