Using same serial port instances on multiple forms

霸气de小男生 提交于 2020-01-03 06:37:10

问题


I am quite new to C# and I am trying to use one common serial port for 3 different forms: Form2, Form3, Form4

Form1.cs isn't needed for this because it's just needed to launch the programs of the other forms. Basically, all 3 forms must receive data from the same serial port at the same time. The problem I am facing is that only one form can receive data from the serial port, but the other two forms can't.

I found a question similar to this:

Using same serial port data received event on two different forms

Is that problem similar to mine? If yes, can I know where should I place the sample code in the aforementioned link in my code?

Can someone please help with this? Thanks in advance!

Form1:

public partial class Form1 : Form
{
    public Form1()
    {
        InitializeComponent();
    }

    private void button1_Click(object sender, EventArgs e)
    {
        Form2 f2 = new Form2();
        f2.Show();
        Form3 f3 = new Form3();
        f3.Show();
        Form4 f4 = new Form4();
        f4.Show();
    }

    private void button2_Click(object sender, EventArgs e)
    {
        this.Close();
    }
}

Form2:

public partial class Form2 : Form
{
    GMapControl MainMap = new GMapControl();
    //Initialise data type for latituide and longitude
    double lat, lng;
    //Initialise customise marker (plane maker). Declared as m.
    GMapMarkerImage m = new GMapMarkerImage(new PointLatLng());
    GMapOverlay overlayOne;

    public Form2()
    {
        InitializeComponent();

        SuspendLayout();

        overlayOne = new GMapOverlay(MainMap, "OverlayOne");
        MainMap.MapProvider = GMapProviders.YahooMap;

        MainMap.SetCurrentPositionByKeywords("Singapore");
        MainMap.MinZoom = 1;
        MainMap.MaxZoom = 24;
        MainMap.Zoom = 13;
        MainMap.CanDragMap = true;
        MainMap.DragButton = MouseButtons.Left;
        MainMap.Dock = DockStyle.Fill;
        MainMap.Manager.Mode = AccessMode.ServerAndCache;

        Controls.Add(MainMap);
        ResumeLayout(true);


    }

    public void button1_Click(object sender, EventArgs e)
    {
        if (!serialPort1.IsOpen)    //if serial port is not open
            try
            {
                serialPort1.Open(); //Open Serial Port
                if (lat != 0 && lng != 0)  //Display marker only when GPS has receive data
                {
                    overlayOne.Markers.Add(m);          //Add marker on the position given to the overlayOne layer
                    MainMap.Overlays.Add(overlayOne);   //Add overlayOne layer to the MainMap layer
                }
            }
            catch
            {
                //A message box will display this message, informing user either a wrong port has been chosen, or have not been plugged in.
                MessageBox.Show("There was an error. Please make sure that the correct port was selected, and the device, plugged in.");
            }

    }

    public void button2_Click(object sender, EventArgs e)
    {
        if (serialPort1.IsOpen)                // if Serial Port is open
        {
            serialPort1.Close();               //Close Serial
            overlayOne.Markers.Remove(m);
        }
    }

    //When microsoft visual studio receive data
    public void serialPort1_DataReceived(object sender, System.IO.Ports.SerialDataReceivedEventArgs e)
    {
        this.Invoke(new EventHandler(DoUpdate));    //for function DoUpdate

        //Pause Microsoft Visual Studio for 100 milliseconds from receiving data, 
        //to ensure serialPort can be close successfully
        Thread.Sleep(100);
    }

    //Function for updating data. Declared as DoUpdate.
    public void DoUpdate(object sender, EventArgs e)
    {
        string[] c = serialPort1.ReadLine().Split(',');  //Stored data seperately by using array & using the Split() function

        lat = Convert.ToDouble(c[9]);               //Convert Latitude string data to double data
        lng = Convert.ToDouble(c[10]);              //Convert Longitude string data to double data

        //Input lat and lng data in m.
        //Updating the position of the marker
        m.Position = new PointLatLng(lat, lng);

    }
}

Form3:

    public partial class Form3 : Form
    {
        public Form3()
        {
            InitializeComponent();

        }

        private void pictureBox1_Click(object sender, EventArgs e)
        {
            if (!serialPort1.IsOpen)    //if serial port is not open
                try
                {
                    serialPort1.Open(); //Open Serial Port

                    //Enable blocks to have colour
                    // ...
                }
                catch
                {
                    //A message box will display this message, informing user either a wrong port has been chosen, or have not been plugged in.
                    MessageBox.Show("There was an error. Please make sure that the correct port was selected, and the device, plugged in.");
                }

        }

        private void button2_Click(object sender, EventArgs e)
        {
            if (serialPort1.IsOpen)                // if serial port is open
            {
                serialPort1.Close();                   // Close serial Port 

                //Clear data in textboxes
                FrontSonar.Text = "    ";
                LeftSonar.Text = "   ";
                RightSonar.Text = "    ";

                //Clear colours in the boxes
                // ...
            }
        }

        private void serialPort1_DataReceived(object sender, System.IO.Ports.SerialDataReceivedEventArgs e) //When microsoft visual studio receive data
        {
            this.Invoke(new EventHandler(DoUpdate1)); //To update and ensure sonar data infront of UAV can be displayed without error
            this.Invoke(new EventHandler(DoUpdate2)); //To update and ensure sonar data left side of UAV can be displayed without error
            this.Invoke(new EventHandler(DoUpdate3)); //To update and ensure sonar data on the right side of UAV can be displayed without error

            Thread.Sleep(100);
        }

        private void DoUpdate1(object s, EventArgs e) //Display for Sonar infront of UAV
        {
            string[] c = serialPort1.ReadLine().Split(',');  //Stored data seperately by using array & using the Split() function
            FrontSonar.Text = c[1] + "\n";
            double d = Convert.ToDouble(c[1]);

            if (d > 500)
            {
                //Fill blocks with green
                this.rectangleShape1.FillColor = System.Drawing.Color.Green;
                this.rectangleShape2.FillColor = System.Drawing.Color.Green;
                this.rectangleShape3.FillColor = System.Drawing.Color.Green;
            }
            else
                if (d > 400 && d <= 500)
                {
                    //Fill block with Orange colour
                    this.rectangleShape1.FillColor = System.Drawing.Color.Orange;
                    this.rectangleShape2.FillColor = System.Drawing.Color.Orange;

                    //Fill block with Lavender colour
                    this.rectangleShape3.FillColor = System.Drawing.Color.Lavender;
                }
                else
                    if (d <= 400)
                    {
                        //Fill block with red colour
                        this.rectangleShape1.FillColor = System.Drawing.Color.Red;

                        //Fill block with Lavender colour
                        this.rectangleShape2.FillColor = System.Drawing.Color.Lavender;
                        this.rectangleShape3.FillColor = System.Drawing.Color.Lavender;
                    }

        }


        private void DoUpdate2(object s, EventArgs e) //Display for Sonar on the left side of UAV
        {
            string[] c = serialPort1.ReadLine().Split(',');  //Stored data seperately by using array & using the Split() function
            // ....

        }

        private void DoUpdate3(object s, EventArgs e) //Display for Sonar on the right side of UAV
        {
            string[] c = serialPort1.ReadLine().Split(',');  //Stored data seperately by using array & using the Split() function
            // ...
        }    
    }

Form4: (Still in progress)

public partial class Form4 : Form
{
    public Form4()
    {
        InitializeComponent();
    }
}

回答1:


Yes, you can. Below is key points to achieve this:

  1. Open serial port once, your approach if (!port.IsOpened) { port.Open(); } is right, extract this in a static method and call in each form (f2, f3, f4) to avoid copy/paste of this code snippet.

  2. serialPort variable should be shared across all three forms, so the same opened and initialized port instance would be accessible for all forms. Considering code you've provided, create and initialize, open port in Form1 class, then pass initialized instance of serialPort into other form classes via constructor injection, basically add SerialPort port constructor parameter for Form2,3,4 classes and then:

    // renamed button1_Click
    private void OnSetup(object sender, EventArgs e)
    {
        this.port = new SerialPort(...);
        // TODO: initialize port
    
        Form2 f2 = new Form2(this.port);
        f2.Show();
        Form3 f3 = new Form3(this.port);
        f3.Show();
        Form4 f4 = new Form4(this.port);
        f4.Show();
    }
    
  3. Then in each form constructor just subscribe to serialPort.DataReceived event and that's it.

    public Form2(SerialPort port)
    {
         port.DataReceived += ...
    }
    

Some recommendations,

  • Give variables and methods more descriptive names rather than form1, form2, c, d, button2_Click
  • Avoid magic numbers, extract constants in variables and give descriptive names, for instance there are multiple occurences of 400, 500 magic numbers, it is not clear for what they are.
  • In comments to a code you saying Pause Microsoft Visual Studio..., microsoft visual studio receives data..., this is not correct, execution of your application (but not Visual Studio) will be paused while Thread.Sleep() and your applciation will receive an incomming serial port data, Visual Studio is just a development environment and in such cases dos not involved in a port communication directly.


来源:https://stackoverflow.com/questions/12617116/using-same-serial-port-instances-on-multiple-forms

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!