首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >线程和跨线程在C#.NET中,如何从另一个线程更改ComboBox数据?

线程和跨线程在C#.NET中,如何从另一个线程更改ComboBox数据?
EN

Stack Overflow用户
提问于 2011-07-02 18:03:34
回答 3查看 5.6K关注 0票数 1

我需要在我的应用程序中使用线程,但我不知道如何执行交叉线程操作。

我希望能够更改form对象(在本例中为Combo Box)的文本,从另一个线程中,我得到了错误:

代码语言:javascript
复制
Cross-thread operation not valid: Control 'titlescomboBox' accessed from a thread other than the thread it was created on.

我真的不知道如何使用invoke和begin invoke函数,所以我真的在寻找一个非常简单的例子和解释,这样我就可以了解它了。

此外,任何初学者教程都会很棒,我找到了一些,但它们都是如此不同,我不知道我需要做什么来执行交叉线程操作。

代码如下:

代码语言:javascript
复制
    // Main Thread. On click of the refresh button
    private void refreshButton_Click(object sender, EventArgs e)
    {
        titlescomboBox.Items.Clear();
        Thread t1 = new Thread(updateCombo);
        t1.Start();
    }

    // This function updates the combo box with the rssData
    private void updateCombo()
    {
        rssData = getRssData(channelTextBox.Text);       // Getting the Data
        for (int i = 0; i < rssData.GetLength(0); i++)   // Output it
        {

            if (rssData[i, 0] != null)
            {

              // Cross-thread operation not valid: Control 'titlescomboBox' 
              // accessed from a thread other than the thread it was created on.

              titlescomboBox.Items.Add(rssData[i, 0]);   // Here I get an Error

            }
            titlescomboBox.SelectedIndex = 0;
        }
    }
EN

回答 3

Stack Overflow用户

回答已采纳

发布于 2011-07-02 18:09:18

我使用下面的helper类:

代码语言:javascript
复制
public static class ControlExtensions
{
    public static void Invoke(this Control control, Action action)
    {
        if (control.InvokeRequired)
        {
            control.Invoke(new MethodInvoker(action), null);
        }
        else
        {
            action.Invoke();
        }
    }
}

现在,您可以在调用之前调用类似MyCombo.Invoke(() => { MyCombo.Items.Add(something); }) -或任何其他控件(如表单)的内容,因为它们都是在主线程上创建的。

问题是,控件只能从创建它们的线程(在本例中是主应用程序线程)访问。

HTH

票数 8
EN

Stack Overflow用户

发布于 2011-07-02 18:19:59

引发此异常是因为您试图访问在另一个线程上创建的控件成员。使用控件时,应仅从在其上创建控件的线程访问控件成员。

通过提供InvokeRequeired属性,控件类可以帮助您了解控件在创建的线程上是否为no。因此,如果'control.InvokeRequeired‘返回true,则表明您在不同的线程上。来帮你一把。控件支持InvokeBeginInvoke方法,这些方法将处理控件主线程的方法的执行。所以:

如果你使用的是3.5或更高版本,我建议你使用Eben Roux在他的答案中显示的扩展方法。

对于2.0:

代码语言:javascript
复制
// This function updates the combo box with the rssData
private void updateCombo()
{
    MethodInvoker method = new MethodInvoker(delegate()
    {
    rssData = getRssData(channelTextBox.Text);       // Getting the Data
    for (int i = 0; i < rssData.GetLength(0); i++)   // Output it
    {

        if (rssData[i, 0] != null)
        {

          // Cross-thread operation not valid: Control 'titlescomboBox' 
          // accessed from a thread other than the thread it was created on.

          titlescomboBox.Items.Add(rssData[i, 0]);   // Here I get an Error

        }
        titlescomboBox.SelectedIndex = 0;
    }
    });

    if (titlescomboBox.InvokeRequired)//if true then we are not on the control thread
    {
         titlescomboBox.Invoke(method);//use invoke to handle execution of this delegate in main thread
    }
    else
    {
        method();//execute the operation directly because we are on the control thread.
    }
}

如果您使用C# 2.0,则如下所示

票数 1
EN

Stack Overflow用户

发布于 2011-07-02 18:07:45

看看这个What is the best way to update form controls from a worker thread? -它应该能解决你的问题。

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

https://stackoverflow.com/questions/6556330

复制
相关文章

相似问题

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