无法在后台工作程序中访问 TextBox.Text
Can't access TextBox.Text in Background worker
我有一个 winforms 应用程序,最初设计为具有不同的顺序功能,可通过按钮手动触发(4 个按钮没有相应的后台程序,4 个按钮有相应的后台程序,总共 8 个按钮)。每个按钮同步进行一些快速设置,然后触发后台工作人员异步完成工作。这可能是一项繁重的工作。
我们决定使用一个 "express" 选项来完成 4 个带有默认选项的按钮的所有工作。不幸的是我没有把它设计成我应该设计的模块化。
我所做的是让 ExpressButton 调用第 5 个后台工作程序,后者依次按顺序在每个按钮上调用 InvokeOnClick。幸运的是,首先调用了 4 个非异步按钮点击。我正在使用 AutoResetEvent 在单击每个顺序按钮时阻止第 5 个 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 我有 2 个文本框供用户输入信息。
在backgroundworker1(对应上面的button5)中,我可以访问第一个TextBox的.Text 属性。
但是在backgroundworker2(对应button6)中,我无法访问另一个TextBox的.Text 属性。
我可以在 button6 单击事件中一直访问它,直到我调用 RunWorkerAsync()。
一旦我在 backgroundworker2 中尝试访问 TextBox.Text 就会冻结程序。也不例外,就是停了。
这是我的理论:
backgroundworker1 called/run 没有来自 button5 click 事件的参数
backgroundworker2 是 called/run,参数来自 button6 单击事件
通过在 RunWorkAsync(params[]) 中传递一个对象列表,我是否导致它不传递原始表单控件的某些上下文?
有趣的是,在主窗体上还有另一个名为 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 的参数列表中。但是我仍然想知道为什么 1 backgroundworker 可以看到主窗体上的文本框而另一个不能。
按照 Austin 所说的去做,并 Invoke() 所有调用。
你只是随机地遇到了这个异常(我不在乎它是否一致),任何从工作线程调用 UI 都可能导致异常,因为只有主线程必须访问 UI.
我敢打赌,当您第一次访问 .Text 属性 时,控件本身不需要重绘,但第二次需要,所以您将以 cross-threading 结束异常。
我有一个 winforms 应用程序,最初设计为具有不同的顺序功能,可通过按钮手动触发(4 个按钮没有相应的后台程序,4 个按钮有相应的后台程序,总共 8 个按钮)。每个按钮同步进行一些快速设置,然后触发后台工作人员异步完成工作。这可能是一项繁重的工作。
我们决定使用一个 "express" 选项来完成 4 个带有默认选项的按钮的所有工作。不幸的是我没有把它设计成我应该设计的模块化。
我所做的是让 ExpressButton 调用第 5 个后台工作程序,后者依次按顺序在每个按钮上调用 InvokeOnClick。幸运的是,首先调用了 4 个非异步按钮点击。我正在使用 AutoResetEvent 在单击每个顺序按钮时阻止第 5 个 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 我有 2 个文本框供用户输入信息。
在backgroundworker1(对应上面的button5)中,我可以访问第一个TextBox的.Text 属性。 但是在backgroundworker2(对应button6)中,我无法访问另一个TextBox的.Text 属性。 我可以在 button6 单击事件中一直访问它,直到我调用 RunWorkerAsync()。 一旦我在 backgroundworker2 中尝试访问 TextBox.Text 就会冻结程序。也不例外,就是停了。
这是我的理论: backgroundworker1 called/run 没有来自 button5 click 事件的参数 backgroundworker2 是 called/run,参数来自 button6 单击事件 通过在 RunWorkAsync(params[]) 中传递一个对象列表,我是否导致它不传递原始表单控件的某些上下文? 有趣的是,在主窗体上还有另一个名为 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 的参数列表中。但是我仍然想知道为什么 1 backgroundworker 可以看到主窗体上的文本框而另一个不能。
按照 Austin 所说的去做,并 Invoke() 所有调用。
你只是随机地遇到了这个异常(我不在乎它是否一致),任何从工作线程调用 UI 都可能导致异常,因为只有主线程必须访问 UI.
我敢打赌,当您第一次访问 .Text 属性 时,控件本身不需要重绘,但第二次需要,所以您将以 cross-threading 结束异常。