简体   繁体   English

C#.NET 中的线程和交叉线程,如何从另一个线程更改 ComboBox 数据?

[英]Threading & Cross Threading in C#.NET, How do I change ComboBox Data from another Thread?

I need to use threading in my app, but I don't know how to perform a cross threading operation.我需要在我的应用程序中使用线程,但我不知道如何执行跨线程操作。

I want to be able to change the text of a form object (in this case a Combo Box), from another thread, I get the error:我希望能够从另一个线程更改表单 object(在本例中为组合框)的文本,但出现错误:

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

I don't really understand how to use the invoke and begin invoke functions, So im really looking for a dead simple example and explanation for this so I can learn around that.我真的不明白如何使用调用和开始调用函数,所以我真的在寻找一个简单的例子和解释,这样我就可以学习了。

Also any beginner tutorials would be great, I found a few, but their all so different, I don't understand exactly what I need to do to perform cross threading ops.此外,任何初学者教程都会很棒,我发现了一些,但它们都如此不同,我不明白我需要做什么才能执行跨线程操作。

Here is the code:这是代码:

    // 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;
        }
    }

I use the following helper class:我使用以下助手 class:

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();
        }
    }
}

Now you can call something like MyCombo.Invoke(() => { MyCombo.Items.Add(something); }) --- or any other control (such as the form) before the invoke since they are all created on the main thread.现在您可以在调用之前调用MyCombo.Invoke(() => { MyCombo.Items.Add(something); }) --- 或任何其他控件(例如表单),因为它们都是在 main 上创建的线。

The thing is that controls can only be accessed from the thread they were created on (the main application thread in this case).问题是控件只能从创建它们的线程(在本例中为主应用程序线程)访问。

HTH HTH

This exception is thrown because of you are trying to access to a control members that is created on another thread.抛出此异常是因为您试图访问在另一个线程上创建的控件成员。 When using controls you should access the control members only from the thread that the control created on.使用控件时,您应该只从控件创建的线程访问控件成员。

The control class helps you to know weather the control is no on the thread that is created on or not by providing InvokeRequeired property.控件 class 通过提供InvokeRequeired属性帮助您了解控件是否在创建的线程上。 so if 'control.InvokeRequeired' returns true that indicates that you are on a different thread.因此,如果“control.InvokeRequeired”返回 true,则表明您在不同的线程上。 to help you out.来帮助你。 Control support Invoke and BeginInvoke methods that will handle the execution of method to the control main thread.控件支持将处理方法执行到控件主线程的InvokeBeginInvoke方法。 So:所以:

If you are using 3.5 and above, I suggest you to use the extension method that Eben Roux show in his answer.如果您使用的是 3.5 及更高版本,我建议您使用Eben Roux在他的回答中显示的扩展方法。

For 2.0:对于 2.0:

// 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.
    }
}

if you use C# 2.0 this如果您使用 C# 2.0 这个

Take a look at this What is the best way to update form controls from a worker thread?看看这个从工作线程更新表单控件的最佳方法是什么? - it should resolve your issue. - 它应该可以解决您的问题。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM