0

在重新设计我的应用程序以包含更灵活的设计后,我在从另一个从线程内运行的类访问位于 MAINFORM 上的方法时遇到了一些麻烦。下面是一些代码片段,显示我正在尝试做的事情:

主要形式:

public void setAlarmColour(byte[] result, int buttonNumber)
    {
        if (result != null)
        {
            this.Invoke((MethodInvoker)delegate
            {
                //txtOutput1.Text = (result[4] == 0x00 ? "HIGH" : "LOW"); // runs on UI thread

                if (result[4] == 0x00)
                {
                    this.Controls["btn" + buttonNumber].BackColor = Color.Green;
                }
                else
                {
                    this.Controls["btn" + buttonNumber].BackColor = Color.Red;
                }


            });

        }


    }

A类:

public void connect(IDeviceInterface device)
    {
        //send data
        byte[] bData = new byte[71];
        bData[0] = 240;
        bData[1] = 240;
        bData[2] = 0;
        bData[3] = 1;
        bData[68] = 240;
        bData[69] = 240;
        bData[70] = this.CalculateCheckSum(bData);


        try
        {

            byte[] result = this.SendCommandResult(device.deviceIPAddress, device.devicePort, bData, 72);
            //send byte + buttonNumber to setAlarmColour on main thread here.

        }
        catch (Exception ex)
        {
            MessageBox.Show(ex.ToString());
        }

    }

现在,回答几个你可能想问的问题,为什么我不想做标题中解释的一些事情。

  • 拥有 connect() 方法的设备类在线程中运行。这是因为我有多个这样的情况,例如,我要监控的每个设备都有一个。
  • 我无法实例化新表单,因为我需要更新当前表单,因此 mainForm main = new mainForm() 不是一个选项
  • 在主表单中的方法上使用静态会导致访问它首先尝试更改的表单控件出现问题,主要是在“this.controls []”部分。尽管如果有人对此有解决方法,我对想法持开放态度
  • 我不想传递对主表单的引用 IF POSSIBLE 因为它可能会在任何地方处理这个问题,而且据我所知,这被认为是不好的做法,特别是随着项目规模的增加。我在较早的版本上已经这样做了,在我到达我需要去的地方之前,我必须通过这个参考大约 3/4 次。

有没有办法通过使用委托/事件等来做到这一点?我已经尝试阅读有关这样做的内容,但其中一些似乎令人困惑,我不确定发生了什么。另外,就像我说的,我对新想法持开放态度,所以如果你能告诉我一种使用我以有效方式排除的选项的方法,那么我是开放的。

有谁知道我如何从 A 类的主窗体中访问此方法?ps如果有人需要更多信息,请询问。

编辑 1:根据 jon skeet 的想法,我决定尝试实施事件来处理这个问题。虽然我遇到了一些问题......

我的表单唯一知道该类的时间是它根据我正在创建的 A 类的条目/实例的数量动态创建它们。在我的 A 类中,我创建了:

 public event EventHandler setAlarmColour = delegate { };

然后我在同一个类中触发事件:

 this.setAlarmColour(this, new EventArgs());

并在类的动态创建过程中订阅事件,例如:

 bfdevice.setAlarmColourDelegate += new EventHandler(setAlarmColour);

其中 bfdevice = class A 和 setAlarmColourDelegate 是事件处理程序,而 setAlarmColour 是我试图访问的主窗体中的方法,但我需要将参数传递给

 EventHandler(setAlarmColour)

即“byte []result,int buttonNumber”,因为目前我得到“没有重载“setAlarmColour”匹配委托“System.EventHandler”有什么想法吗?

这里的问题是我需要发送到 setAlarmColour 的参数仅在 A 类中是已知的,这不是我订阅事件的地方。因此我不能做 setAlarmColour(result, buttonNumber) 因为 mainform 没有参考这些。

4

1 回答 1

3

听起来ClassA可能会暴露一个CommandReceived事件。然后,表单将为 的每个实例订阅该事件ClassA。这实际上ClassA是在委托事件处理程序中传递对 , 的引用,但它都是隐藏的。

从根本上说,每个实例都必须以某种方式ClassA返回到表单的实例。我强烈建议您不要通过静态变量来执行此操作,这会引入紧密耦合并降低可测试性。

如果您不喜欢事件的想法,则必须将引用传递给ClassA其他方式 - 例如在构造函数中。在这种情况下,您可能会在两者之间引入一个接口 -ClassA的构造函数将具有接口类型的参数,并且您的表单将实现该接口。这将放松两者之间的耦合。

于 2012-05-29T13:09:36.577 回答