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

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

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

  1. 有一个主要表单托管一些用户控件。

  2. 用户控件执行一些繁重的数据操作,这样如果我直接调用该UserControl_Load方法,则UI在加载方法执行的持续时间内变得无响应。

  3. 为了克服这个问题,我在不同的线程上加载数据(尝试尽可能少地更改现有代码)

  4. 我使用了后台工作线程来加载数据,完成后会通知应用程序已经完成了它的工作。

  5. 现在来了一个真正的问题。所有UI(主窗体及其子用户控件)都是在主要主线程上创建的。在usercontrol的LOAD方法中,我基于userControl上的某些控件(如文本框)的值来获取数据。

伪代码看起来像这样:

代码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.

    }

}

它给出的例外是


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


为了更多地了解这一点,我做了一些谷歌搜索,并提出了一个建议,如使用下面的代码


代码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执行。加载任务再次由父线程完成,而不是我生成的第三个。


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


如何解决这个问题以及阻止执行第1行的影响是什么?


情况是这样的:我想根据控件的值将数据加载到全局变量中。我不想从子线程更改控件的值。我不打算从子线程中做到这一点。


因此只访问该值,以便可以从数据库中获取相应的数据。


互换的青春
浏览 808回答 5
5回答

手掌心

您只想使用Invoke或BeginInvoke来完成更改UI所需的最少工作量。你的“重”方法应该在另一个线程上执行(例如通过BackgroundWorker),然后使用Control.Invoke / Control.BeginInvoke来更新UI。这样你的UI线程就可以自由处理UI事件等。请参阅我的线程文章以获取WinForms示例&nbsp;- 虽然文章是在BackgroundWorker到达现场之前编写的,但我担心我没有在这方面更新它。BackgroundWorker只是略微简化了回调。

POPMUISE

我遇到了这个问题,FileSystemWatcher发现以下代码解决了这个问题:fsw.SynchronizingObject = this然后,控件使用当前表单对象来处理事件,因此将在同一个线程上。

守着一只汪

我现在知道太晚了。但是,即使在今天,如果您在访问跨线程控件时遇到问题?这是迄今为止最短的答案:PInvoke(new&nbsp;Action(()&nbsp;=> &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;{ &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;label1.Text&nbsp;=&nbsp;"WooHoo!!!"; &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;}));这是我从线程访问任何表单控件的方式。
打开App,查看更多内容
随时随地看视频慕课网APP