【问题标题】:C# cross thread operation exception when I call my method from Form1当我从 Form1 调用我的方法时,C# 跨线程操作异常
【发布时间】:2013-08-28 22:36:03
【问题描述】:

这是我在 Form2 上设置某些组件状态的小方法。当我在加载它时从 Form2 调用它时。工作正常,但是当我从 Form1 调用它时(需要更新某些状态)我得到一个异常:

System.Windows.Forms.dll 中出现“System.InvalidOperationException”类型的未处理异常

附加信息:跨线程操作无效:控件“button1”从创建它的线程以外的线程访问。

public void SetleMotor1()
{
    button1.Enabled = true;
    button2.Enabled = false;
    if (Form1.Motor1.Calibstate == 3)
        label4.Text = "Befejezve";
    else
        label5.Text = "Megállt";

    if (Form1.Motor1.Calibrated)
    {
        label21.Text = "Igen";
        label6.Text = Convert.ToString(Form1.Motor1.MMImp);
    }
    else
    {
        label21.Text = "Nem";
        label6.Text = "-";
    }
}

请问,我错过了什么?

这是 Form1 中调用 Form2 上的方法的代码:

void sp_DataReceived(object sender, SerialDataReceivedEventArgs e)
{
    // reading the data etc etc etc...then evaluating:
    case 1:
        if ((data[1] == 40) && (Motor1.Calibstate == 3))
        {
            long impulses = (65536 * data[2] + 256 * data[3] + data[4]);
            Form2.SetleMotor1(); // <----- this is where it happens
            Motor1.Calibstate = 0;
            zaloguj("A Motor 1 kalibrációja befejezve");
            if (Motor1.Debug)
                zaloguj("A Motor 1 köre " + Convert.ToString(impulses) + " impulzus");

            Motor1.MMImp = Convert.ToInt32(impulses / 360);
            Motor1.Calibrated = true;
            if (Motor1.Debug)
                zaloguj("M1Imp/deg: " + Convert.ToString(Motor1.MMImp));
        }
        break;
        // other similar code ...
}

【问题讨论】:

  • 你可以把你调用方法的代码放在这里。
  • 另外请告诉我们您是在设计器中还是在代码中创建button?如果在代码中,也向我们展示。
  • 所有都是在设计器中创建的,我几乎改变了已经创建的对象的属性。我从 Form1 上的串行端口事件处理程序(我使用 Visual Studio 中给出的标准串行端口)调用此代码。这可能是一个线程轮询 COM 端口的状态,我之前没有意识到这一点。代码(串行端口处理程序)相当长,但我会在几个小时后粘贴重要的部分,一旦我到达我的笔记本电脑)。
  • 有一个全局变量 Form1.Motor1.Calibstate - 我正在考虑订阅它的值更改或类似的事件并在 Form2 上处理它......这行得通吗?

标签: c#


【解决方案1】:

您需要在表单的线程上调用方法调用。你可以让方法自己做,这样你就不用在调用代码中担心了:

public void SetleMotor1()
{
    if (Form1.InvokeRequired)
    {
        Form1.Invoke(new Action(SetleMotor1));
        return;
    }

    button1.Enabled = true;
    button2.Enabled = false;
    if (Form1.Motor1.Calibstate == 3)
        label4.Text = "Befejezve";
    else
        label5.Text = "Megállt";
    if (Form1.Motor1.Calibrated)
    {
        label21.Text = "Igen";
        label6.Text = Convert.ToString(Form1.Motor1.MMImp);
    }
    else
    {
        label21.Text = "Nem";
        label6.Text = "-";
    }
}

【讨论】:

  • 感谢您的回答。此代码的“我得到最佳重载方法匹配有一些无效参数”错误
  • @IstvanProsinger,感谢您指出。似乎Invoke 不支持直接将 lambda 传递给它,因此请包含在 Action 中。我更正了答案。
  • 好的,我必须为我的案例创建一个 Form1 的实例,但您的代码运行良好。谢谢@Samuel Neff
猜你喜欢
  • 2010-09-05
  • 1970-01-01
  • 2011-03-29
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多