C# Can';t访问文本框。后台工作程序中的文本

C# Can';t访问文本框。后台工作程序中的文本,c#,.net,winforms,backgroundworker,C#,.net,Winforms,Backgroundworker,我有一个winforms应用程序,最初设计为使用按钮手动触发不同的顺序功能(4个按钮没有相应的backgroundworkers,4个按钮有相应的backgroundworkers,总共8个按钮)。每个按钮同步执行一些快速设置,然后启动后台工作程序以异步执行工作。这可能是一项繁重的工作 决定使用一个“快速”选项,该选项完成4个按钮的所有工作,并带有默认选项。不幸的是,我没有把它设计成我应该有的模块化 我所做的是让ExpressButton调用第五个后台工作程序,该工作程序依次调用InvokeOn

我有一个winforms应用程序,最初设计为使用按钮手动触发不同的顺序功能(4个按钮没有相应的backgroundworkers,4个按钮有相应的backgroundworkers,总共8个按钮)。每个按钮同步执行一些快速设置,然后启动后台工作程序以异步执行工作。这可能是一项繁重的工作

决定使用一个“快速”选项,该选项完成4个按钮的所有工作,并带有默认选项。不幸的是,我没有把它设计成我应该有的模块化

我所做的是让ExpressButton调用第五个后台工作程序,该工作程序依次调用InvokeOnClick并按顺序单击每个按钮。幸运的是,4个非异步按钮首先被调用。我正在使用AutoResetEvent在单击每个顺序按钮时阻止第五个backgroundworker

下面是一些伪代码,按钮1-4不调用后台工作人员,按钮5-8调用后台工作人员,以及全局变量中的_resetevent=new AutoResetEvent(false):

 private void backgroundWorker5_DoWork(object sender, DoWorkEventArgs e)    
 {
        ControlEventArgs automationcheck = new ControlEventArgs(expressButton);

        InvokeOnClick(button1, null);
        System.Threading.Thread.Sleep(500);
        InvokeOnClick(button2, null);
        System.Threading.Thread.Sleep(500);
        InvokeOnClick(button3, null);
        System.Threading.Thread.Sleep(500);
        InvokeOnClick(button4, null);
        System.Threading.Thread.Sleep(500);
        InvokeOnClick(button5, automationcheck);
        _resetevent.WaitOne();
        _resetevent.Reset();
        InvokeOnClick(button6, automationcheck);
        _resetevent.WaitOne();
        _resetevent.Reset();
        InvokeOnClick(button7, automationcheck);
        _resetevent.WaitOne();
        _resetevent.Reset();
        InvokeOnClick(button8, automationcheck);
        _resetevent.WaitOne();
        _statusBox.AppendText("Finished" + Environment.NewLine);
}
这就是奇怪的事情。在UI中,我有两个文本框,用户可以在其中输入信息

在backgroundworker1(对应于上面的按钮5)中,我可以访问第一个文本框的.Text属性。 但是,在backgroundworker2(对应于button6)中,我无法访问另一个文本框的.Text属性。 我可以在button6 click事件中访问它,直到调用RunWorkerAsync()。 当我在后台工作2试图访问文本框时,文本会冻结程序。没有例外,它只是停止

以下是我的理论: backgroundworker1在button5 click事件中调用/运行时没有参数 backgroundworker2被调用/运行,参数来自按钮6单击事件 通过在RunWorkAsync(params[])中传递objectlist,是否导致它不传递原始表单控件的某些上下文? 有趣的是,主窗体上还有一个名为statusBox的文本框,我仍然可以在backgroundworker2中访问它,事实上,我一直在使用它进行调试

总而言之

Button 9    
  Backgroundworker 5
    Button 1
    Button 2
    Button 3
    Button 4
    Button 5
      Backgroundworker 1
        Can access TextBox.Text here
    Button 6
      Backgroundworker 2
        Can't access TextBox.Text here
    Button 7
      Backgroundworker 3
         unsure
    Button 8
      Backgroundworker 4
         unsure
最坏情况:


由于button6仍然可以访问文本框,我可以抓取文本并将其传递到runworkerasync的参数列表中。然而,我仍然想知道为什么一个后台工作人员可以在主窗体上看到一个文本框,而另一个不能

照奥斯汀说的做,调用()所有调用

您只是随机遇到这个异常(我不在乎它是否一致),工作线程对UI的任何调用都可能导致异常,因为只有主线程必须访问UI


我打赌,当您第一次访问.Text属性时,控件本身不需要重新绘制,但第二次需要,因此您将以交叉线程异常结束。

您应该使用委托并调用/Invoke required…我可能需要做很多事情,但这个问题与为什么一个后台工作人员可以访问文本框而另一个不能直接相关。这个问题毫无意义。您是否可以从另一个线程访问(有时)UI属性并不重要,因为根据定义,该行为是未定义的。您无法从工作线程更新UI元素,请尝试使用
dispatcher。运行
以更新UI元素。这最终是它的一个变体。细节很有趣,两个文本框是连接字符串,前两个按钮尝试自动检测,后两个按钮验证。当所有这些都一步一步完成时,每次验证都需要检查另一个框是否已经验证。如果是,则不执行任何操作,但如果不是当前单击,则需要在另一个框上设置ReadOnly=false。显然,当按顺序调用这些命令时,一个始终不会被验证,因此其中一次单击变成ReadOnly=false。我认为这导致需要重新绘制。为了修复它,我意识到在验证后将连接字符串存储在全局变量中,然后在每次需要连接字符串时引用TextBox的.Text属性更有意义。现在看起来很明显,但我对整个UI都不熟悉,这是一个很大的错误,因为我对线程基础设施有更好的了解(至少在winforms中是这样)