c# windows形成自定义控件跨线程操作
本文关键字:线程 操作 自定义控件 windows | 更新日期: 2023-09-27 18:17:55
我有一个主窗口窗体,在该窗体中我有代表应用程序中不同屏幕的自定义控件。我想访问这个控件的子控件。有些事我还没明白…有时我得到这样的错误:
跨线程操作无效:控制从线程访问的'lblText'而不是创建它的线程。
但有时一切正常。我不完全明白为什么会出错…可能是外部设备(MEI BillAcceptor)的东西,它有一个事件(在Form1类内部),对控件进行更改……所以让我写一个简单的代码…
//user control
public partial class Screen2 : UserControl
{
public void changeValue(string txt)
{
lblText.Text = txt;
}
}
和方法changeValue从form1调用时,特定的事件上升…
public partial class Form1 : Form
{
public Form1()
{
InitializeComponent();
BillAcceptor.SomeBillAcceptorEvent +=
new SomeBillAcceptorEventHandler(changeText);
}
private void changeText(object sender, EventArgs args)
{
_screen2.changeValue("some text");
}
}
所以最烦人的事情是,有时一切都是正常的…所以我的问题是"我必须在这里使用Invoke吗?"或者我如何通过对应用程序进行更少的更改来解决这个问题…
在处理程序中。像这样做。
if (this.InvokeRequired)
{
Invoke(new MethodInvoker(() =>
{
_screen2.changeValue("some text");
}));
}
else
{
_screen2.changeValue("some text");
}
我猜事件是在主UI线程之外的另一个线程上引发的。
如果有可能从其他线程调用该方法,则需要使用Invoke
您可以检查this.InvokeRequired()
,如果为真,则使用invoke,如果为假则进行正常调用。
由于thread unsafe call
你应该只在程序
中进行线程安全的调用查看此链接
简短的回答是肯定的,您必须使用Invoke。如果您需要详细信息,请参阅此问题及其公认答案。
顺便说一下,异常只在某些时候被抛出的原因归结为时间问题。你现在有一个竞争条件,有时你很幸运,有时你没有。顺便说一下,这里有一个非常方便的模式。
- 将任何设置form值的代码重构为自己的私有void方法。
- 在这个新方法中,调用
InvokeRequired
。如果它返回true,调用Invoke,传递当前方法以便递归返回。如果返回false,则继续进行更改。 - 从事件处理程序调用这个新方法。
private void ChangeScreen2() {
if (this.InvokeRequired) {
this.Invoke(new MethodInvoker(ChangeScreen2));
}
else {
_screen2.changeValue("some text");
}
}
private void changeText(object sender, EventArgs args)
{
ChangeScreen2();
}
的想法是,你隔离所有的代码修改的形式到这些方法,总是开始检查InvokeRequired
和Invoke
本身,如果需要的话。此模式适用于。net 1.0以后的版本。要获得更简洁的方法,请参阅对这个问题的公认答案,它适用于。net 3.0和更高版本。