首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >从另一个线程获取控件的属性

从另一个线程获取控件的属性
EN

Stack Overflow用户
提问于 2012-05-13 21:01:49
回答 2查看 6.1K关注 0票数 3

我想从窗体中的BackgroundWorker获取控件的属性:

代码语言:javascript
复制
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
}

有谁能建议最简单和最容易的方法来做这件事吗?

EN

回答 2

Stack Overflow用户

回答已采纳

发布于 2012-05-13 21:12:03

让我再试一次...

1.)将ListView拖到窗体上

2.)将BackgroundWorker拖到窗体上

3.)创建一个遍历ListViewItem集合的方法

代码语言:javascript
复制
private void LoopThroughListItems()
{
    foreach (ListViewItem i in listView1.CheckedItems)
        DoSomething(); 

}

4.)添加代码以在BackgroundWorker的DoWork事件内调用LoopThroughListItems()

代码语言:javascript
复制
private void backgroundWorker1_DoWork(object sender, DoWorkEventArgs e)
{
    LoopThroughListItems();
}

5.)在表单中,加载-在主线程上执行代码(可以工作),然后在backgroundWorkder线程上执行代码(失败)

代码语言:javascript
复制
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

代码语言:javascript
复制
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

票数 2
EN

Stack Overflow用户

发布于 2012-05-16 04:51:45

尝试如下所示:

代码语言:javascript
复制
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Linq;
using System.Windows.Forms;

namespace WindowsFormsApplication1
{
    public partial class Form1 : Form
    {
        public Form1()
        {
            InitializeComponent();
        }

        private void OnClick(object sender, EventArgs e)
        {
            backgroundWorker1.RunWorkerAsync();
        }

        private void OnDoWork(object sender, DoWorkEventArgs e)
        {
            foreach (ListViewItem i in GetItems(listView1))
            {
                DoSomething(i);
            }
        }

        private IEnumerable<ListViewItem> GetItems(ListView listView)
        {
            if (InvokeRequired)
            {
                var func = new Func<ListView, IEnumerable<ListViewItem>>(GetItems);
                return (IEnumerable<ListViewItem>)Invoke(func, new[] { listView });
            }
            // Create a defensive copy to avoid iterating outsite UI thread
            return listView.CheckedItems.OfType<ListViewItem>().ToList();
        }

        private void DoSomething(ListViewItem item)
        {
            if (InvokeRequired)
            {
                var action = new Action<ListViewItem>(DoSomething);
                Invoke(action, new[] { item });
                return;
            }
            // Do whatever you want with i
            item.Checked = false;
        }
    }
}

然而,你的问题真的很笼统。如果你分享更多的细节,也许会有一个更容易或更好的解决方案。

票数 1
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/10571949

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档