跨线程操作无效:控制从比它创建的线程以外的线程访问 [英] Cross-thread operation not valid: Control accessed from a thread other than the thread it was created on

查看:440
本文介绍了跨线程操作无效:控制从比它创建的线程以外的线程访问的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我有一个场景。 (Windows窗体,C#.NET)

I have a scenario. (Windows Forms, C#, .NET)


  1. 有它承载了一些用户控件主要形式。

  2. 用户控件做一些繁重的数据操作,例如,如果我直接调用 UserControl_Load 方法变得无响应,为负载方法执行期间的用户界面。

  3. 要克服不同的线程这一点,我加载数据(试图改变现有的code少,我可以)

  4. 我用了一个后台工作线程将被加载数据,它完成了它的工作完成后会通知应用程序。

  5. 现在,来了一个真正的问题。所有的UI(主要形式及其子用户控件)是主要的主线程上创建的。在该用户的Load方法我基于对用户控件一些控制(如文本框)的值取数据。

  1. There is a main form which hosts some user control.
  2. The user control does some heavy data operation, such that if I directly call the UserControl_Load method the UI become nonresponsive for the duration for load method execution.
  3. To overcome this I load data on different thread (trying to change existing code as little as I can)
  4. I used a background worker thread which will be loading the data and when done will notify the application that it has done its work.
  5. Now came a real problem. All the UI (main form and its child usercontrols) was created on the primary main thread. In the LOAD method of the usercontrol I'm fetching data based on the values of some control (like textbox) on userControl.

伪code是这样的:

code 1

UserContrl1_LoadDataMethod()
{
    if (textbox1.text == "MyName") // This gives exception
    {
        //Load data corresponding to "MyName".
        //Populate a globale variable List<string> which will be binded to grid at some later stage.
    }
}

这给了唯一的例外是

The Exception it gave was

跨线程操作无效:控制从比它创建的线程以外的线程访问

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

要了解更多关于这一点,我做了一些谷歌搜索和建议提出了类似使用以下code

To know more about this I did some googling and a suggestion came up like using the following code

code 2

UserContrl1_LoadDataMethod()
{
    if (InvokeRequired) // Line #1
    {
        this.Invoke(new MethodInvoker(UserContrl1_LoadDataMethod));
        return;
    }

    if (textbox1.text == "MyName") // Now it wont give an exception
    {
    //Load data correspondin to "MyName"
        //Populate a globale variable List<string> which will be binded to grid at some later stage
    }
}

但却但......好像我又回到了起点。再次的应用
变为无响应。这似乎是由于线路#1,如果条件的执行。装载任务由父线程再次完成,而不是在第三我衍生

BUT BUT BUT... it seems I'm back to square one. The Application again become nonresponsive. It seems to be due to the execution of line #1 if condition. The loading task is again done by the parent thread and not the third that I spawned.

我不知道我是否认为这对还是错。我是新来的线程。

I don't know whether I perceived this right or wrong. I'm new to threading.

我如何解决这个问题并且是什么的执行效果1号线,如果块?

How do I resolve this and also what is the effect of execution of Line#1 if block?

的情况是这样的:我想将数据加载到基于控制值的全局变量。我并不想改变从子线程控件的值。我不打算从一个子线程永远做到这一点。

The situation is this: I want to load data into a global variable based on the value of a control. I don't want to change the value of a control from the child thread. I'm not going to do it ever from a child thread.

因此​​,只有在访问的值,以使相应的数据可以从数据库中获取。

So only accessing the value so that the corresponding data can be fetched from the database.

推荐答案

按<一个href=\"http://stackoverflow.com/questions/142003/cross-thread-operation-not-valid-control-accessed-from-a-thread-other-than-the#142108\">SilverHorse's更新评论,你要那么应该像解决方法:

As per SilverHorse's update comment, the solution you want then should look like:

UserContrl1_LOadDataMethod()
{
    string name = "";
    if(textbox1.InvokeRequired)
    {
        textbox1.Invoke(new MethodInvoker(delegate { name = textbox1.text; }));
    }
    if(name == "MyName")
    {
        // do whatever
    }
}

不要在单独的线程中的之前,请认真处理的尝试切换到该控件的线程。例如:

Do your serious processing in the separate thread before you attempt to switch back to the control's thread. For example:

UserContrl1_LOadDataMethod()
{
    if(textbox1.text=="MyName") //<<======Now it wont give exception**
    {
        //Load data correspondin to "MyName"
        //Populate a globale variable List<string> which will be
        //bound to grid at some later stage
        if(InvokeRequired)
        {
            // after we've done all the processing, 
            this.Invoke(new MethodInvoker(delegate {
                // load the control with the appropriate data
            }));
            return;
        }
    }
}

这篇关于跨线程操作无效:控制从比它创建的线程以外的线程访问的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
相关文章
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆