在多个表单上使用相同的串行端口实例

我是C#新手,我正在尝试使用一个通用的串行端口,用于3种不同的forms: Form2, Form3, Form4

这不需要Form1.cs ,因为只需要启动其他表单的程序。 基本上,所有3个表单必须同时从同一个串行端口接收数据。 我面临的问题是只有一个表单可以从串口接收数据,但其他两个表单不能。

我发现了一个与此类似的问题:

在两种不同的表单上使用相同的串口数据接收事件

这个问题跟我的相似吗? 如果是,我可以知道在哪里将示例代码放在我的代码中的上述链接中吗?

有人可以帮忙吗? 提前致谢!

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

窗体2:

 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 // ... } } 

表格4 :(仍在进行中)

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

是的你可以。 以下是实现这一目标的关键点:

  1. 打开串口一次,你的方法if (!port.IsOpened) { port.Open(); } if (!port.IsOpened) { port.Open(); }是的,在静态方法中提取它并调用每个表单(f2,f3,f4)以避免复制/粘贴此代码片段。

  2. serialPort变量应该在所有三个表单中共享,因此所有表单都可以访问相同的打开和初始化的端口实例。 考虑你提供的代码,创建和初始化,在Form1类中打开端口,然后通过构造函数注入将初始化的serialPort实例传递到其他表单类,基本上为Form2,3,4类添加SerialPort port构造函数参数,然后:

     // 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. 然后在每个表单构造函数中只订阅serialPort.DataReceived事件,就是这样。

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

一些建议,

  • 为变量和方法提供更具描述性的名称,而不是form1form2cdbutton2_Click
  • 避免使用幻数,在变量中提取常量并给出描述性名称,例如,有多个出现400 500幻数,但它们的含义并不清楚。
  • 在对您所说的Pause Microsoft Visual Studio...的代码的评论中, microsoft visual studio receives data... ,这是不正确的,当Thread.Sleep()和你的应用程序执行你的应用程序(但不是Visual Studio)时会暂停applciation将收到一个输入串口数据,Visual Studio只是一个开发环境,在这种情况下,dos不直接涉及端口通信。