C# C windows窗体自定义控件跨线程操作
我有一个主窗口窗体,在该窗体中我有表示应用程序中不同屏幕的自定义控件。我想访问此控件的子控件。有些东西我不明白…有时我会犯这样的错误: Cross-thread operation not valid: Control 'lblText' accessed from a thread other than the thread it was created on. 当特定事件发生时,从form1调用方法changeValueC# C windows窗体自定义控件跨线程操作,c#,multithreading,user-controls,invokerequired,C#,Multithreading,User Controls,Invokerequired,我有一个主窗口窗体,在该窗体中我有表示应用程序中不同屏幕的自定义控件。我想访问此控件的子控件。有些东西我不明白…有时我会犯这样的错误: Cross-thread operation not valid: Control 'lblText' accessed from a thread other than the thread it was created on. 当特定事件发生时,从form1调用方法changeValue public partial class Form1 : Form
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线程以外的单独线程上引发的。。像这样做
if (this.InvokeRequired)
{
Invoke(new MethodInvoker(() =>
{
_screen2.changeValue("some text");
}));
}
else
{
_screen2.changeValue("some text");
}
我猜事件是在主UI线程以外的单独线程上引发的。是的,如果可能从其他线程调用该方法,则需要使用Invoke
您可以对此进行检查。InvokeRequired,如果为true,则使用invoke,如果为false,则执行正常调用。是的,如果可能从其他线程调用该方法,则需要使用invoke
您可以对此进行检查。InvokeRequired,如果为true,则使用invoke,如果为false,则执行正常调用。简短的回答是“是”,您必须使用invoke。看 顺便说一句,异常只在某些时候抛出的原因可以归结为时间。你现在有一个比赛条件,有时你会幸运,有时你不会 顺便说一句,这是一个非常方便的模式 重构任何将表单值设置为自己的私有void方法的代码。 在这个新方法中,调用invokererequired。如果返回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();
}
其思想是将所有修改表单的代码隔离到这些方法中,这些方法总是从检查invokererequired开始,如果需要,总是调用它们自己。此模式适用于.NET1.0以后的版本。对于更简洁的方法,请参阅可用于.NET 3.0及更高版本的已接受答案。简短的答案是“是”,您必须使用Invoke。看 顺便说一句,异常只在某些时候抛出的原因可以归结为时间。你现在有一个比赛条件,有时你会幸运,有时你不会 顺便说一句,这是一个非常方便的模式 重构任何将表单值设置为自己的私有void方法的代码。 在这个新方法中,调用invokererequired。如果返回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();
}
其思想是将所有修改表单的代码隔离到这些方法中,这些方法总是从检查invokererequired开始,如果需要,总是调用它们自己。此模式适用于.NET1.0以后的版本。对于更简洁的方法,请参阅可用于.NET 3.0及更高版本的已接受答案。已回答,因此我只需添加以下注释:与UI交互的所有内容都必须在主UI线程上。任何其他工作线程都必须使用Method.Invoke,然后才能直接与UI交互。已回答,因此我将添加以下注释:与UI交互的所有内容都必须在主UI线程上。任何其他工作线程都必须使用Method.Invoke,然后才能直接与UI交互。