1

我有一个主窗口窗体,在该窗体中,我有代表应用程序中不同屏幕的自定义控件。我想访问这个控件的子控件。有些东西我没有在这里......有时我会收到这个错误:

跨线程操作无效:
从线程访问的控件“lblText”
除了创建它的线程。

但有时一切正常。我不完全理解为什么会出现错误......可能是外部设备(MEI BillAcceptor)有一个事件(在Form1类内)对控件进行更改......所以让我写一个简单的代码......

//user control
public partial class Screen2 : UserControl
{
    public void changeValue(string txt)
    {
        lblText.Text = txt;
    }
}

当特定事件发生时,从 form1 调用方法 changeValue...

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 吗?” 或者我如何通过对应用程序的较少更改来解决这个问题......

4

4 回答 4

4

在你的处理程序中。做这样的事情。

        if (this.InvokeRequired)
        {
            Invoke(new MethodInvoker(() => 
            {
                _screen2.changeValue("some text");
            }));
        }
        else
        {
            _screen2.changeValue("some text");
        }

我猜想该事件是在主 UI 线程之外的单独线程上引发的。

于 2011-12-14T15:23:02.067 回答
2

是的,如果有可能从不同的线程调用该方法,则需要使用 Invoke。

您可以检查this.InvokeRequired(),如果为真,则使用调用,如果为假,则进行正常调用。

于 2011-12-14T15:23:27.953 回答
0

这是由于thread unsafe call

您应该只在程序中进行线程安全调用

检查链接。

于 2011-12-14T15:20:13.210 回答
0

简短的回答是肯定的,您必须使用 Invoke。如果您需要详细信息,请参阅此问题及其接受的答案

顺便说一句,仅在某些时候抛出异常的原因归结为时间。你目前有一个比赛条件,有时你很幸运,有时你没有。

顺便说一句,对于这类事情,这里有一个非常方便的模式。

  1. 将任何设置表单值的代码重构为它自己的私有 void 方法。
  2. 在这个新方法中,调用InvokeRequired. 如果它返回 true,则调用 Invoke,传递当前方法以便递归回它。如果它返回 false,请继续进行更改。
  3. 从事件处理程序调用这个新方法。

例如:

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 及更高版本。

于 2011-12-14T15:27:12.643 回答