简体   繁体   中英

how do you access a method from another class / thread without instantiation, static variables or passing references?

After redesigning my application somewhat to incorporate a more flexible design, i'm running into some troubles with accessing a method located on the MAINFORM, from another class which runs from within a thread. below are some code snippets to show what i'm trying to do:

MAIN FORM:

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;
                }


            });

        }


    }

CLASS 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());
        }

    }

now, to answer a few questions you might be thinking to ask, why do i not want to do some of the things explained in the title.

  • the device class which holds the connect() method runs in a thread. this is because i have multiple of these going on, one for each device i'm trying to monitor, for exampl.
  • i can't instantiate a new form as i need to update the current one, therefore mainForm main = new mainForm() isn't an option
  • using static on my method in the main form causes issues with accessing the form controls it's trying to change in the first place, mainly at the "this.controls[]" part. although if anyonyone has a workaround for this, i'm open to ideas
  • i don't want to pass a reference to the main form IF POSSIBLE as it could get messy handing this around everywhere, and as far as i'm aware it's considered bad practise, especially as projects increase in size. i have done this on an earlier version and i had to pass this reference about 3/4 times before i even got to where i needed to go.

is there a way i could do this by using delegates / events or such? i've tried reading about doing this but some of it seems confusing and i'm not sure what's going where. Also, like i said, i'm open to new ideas so if you can show me a way of using the options i ruled out in an efficient way then i'm open minded.

Does anyone have any idea how i can access this method in the main form from class A? ps if anyone needs additional information, simply ask.

edit 1: with ideas from jon skeet, i've decided to try and implement events to handle this problem. i'm running into some problems though...

the only time my form knows about the class is when it dynamically creates them based on how many entries / instances of class A i'm creating. in my class A, i have created:

 public event EventHandler setAlarmColour = delegate { };

then i fire the event in the same class as such:

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

and subscribe to the event during the dynamic creation of the class, as such:

 bfdevice.setAlarmColourDelegate += new EventHandler(setAlarmColour);

where bfdevice = class A and setAlarmColourDelegate is the event handler, and setAlarmColour is my method in mainform i'm trying to access, but i need to pass parameters through to

 EventHandler(setAlarmColour)

namely "byte[]result, int buttonNumber" as currently i'm getting "No overload for "setAlarmColour" matches delegate "System.EventHandler" any ideas?

the problem here is that the parameters i need to send to setAlarmColour are only known in class A, which isn't where i'm subscribing to the event. therefore i cannot do setAlarmColour(result, buttonNumber) as mainform has no reference to these.

It sounds like ClassA could expose a CommandReceived event. The form would then subscribe to that event for each instance of ClassA . This is really passing a reference to ClassA , within the delegate event handler, but it's all hidden.

Fundamentally, each instance of ClassA has to get back to the instance of the form somehow . I would strongly advise you not to do this via a static variable, which would introduce tight coupling and reduce testability.

If you don't like the event idea, you'll have to pass the reference to ClassA some other way - eg in the constructor. In this case you'd probably introduce an interface between the two - ClassA 's constructor would have a parameter of the interface type, and your form would implement the interface. That would loosen the coupling between the two.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM