Hello!
I have a small program written in C# with windows forms to send data bytes using COM ports. I am testing the program on one computer, on two interconnected USB modules supporting serial communication, so that one transmits, the other receives and vice versa. This program allows to see sending data bytes and receiving bytes on two RichTextBoxes of the same application, but... Not as well as I expected. Picture below:
https://learn.microsoft.com/answers/storage/attachments/243193-image.png
The problem is in "Test" card. On the left side I see sending hex bytes. I assumed I wanted to be able to send 1000 random characters one by one (this is done by the for loop) and see the other com port receive those 1000 characters. These characters are seen as received on the right side of the window, however, only after the entire loop has run, i.e. when the entire 1000 characters packet have been sent. However, I dream about the situation that single characters, however, would be sent immediately as soon as they would be in the buffer - not when the entire loop was finally executed. So I mean sending and receiving particular bytes at the same time.
Currently, this option is only for me if I simply run the .exe file twice (in two windows) and make it to send and receive data in this way. I feel that I need a proper usage of multithreading in this situation, but at the moment I cannot find the way to deal with repetitive sending other than this simple for loop. Is there an option to fix that? Any help will be appreciate.
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Windows.Forms;
using System.IO.Ports;
namespace USB_tester
{
public partial class USB_tester : Form
{
System.IO.Ports.SerialPort port1;
System.IO.Ports.SerialPort port2;
delegate void Delegat1();
delegate void Delegat2();
Delegat1 moj_del1;
Delegat2 moj_del2;
public USB_tester()
{
InitializeComponent();
port1 = new SerialPort();
port2 = new SerialPort();
port1.ReadTimeout = 500;
port1.WriteTimeout = 500;
port2.ReadTimeout = 500;
port2.WriteTimeout = 500;
Settings.Enter += new EventHandler(Ustawienia_Enter);
port1.DataReceived += new SerialDataReceivedEventHandler(DataRecievedHandler1);
port2.DataReceived += new SerialDataReceivedEventHandler(DataRecievedHandler2);
moj_del1 = new Delegat1(ShowReceived1);
moj_del2 = new Delegat2(ShowReceived2);
}
private void DataRecievedHandler1(object sender, SerialDataReceivedEventArgs e)
{
rtbTerminal1.Invoke(moj_del1);
}
private void DataRecievedHandler2(object sender, SerialDataReceivedEventArgs e)
{
rtbTerminal2.Invoke(moj_del2);
}
private void ShowReceived1()
{
label2.Text = port1.BytesToRead.ToString();
for (int k = port1.BytesToRead; k > 0; k--)
{
ColoredTerminal(rtbTerminal1, port1.ReadByte().ToString("X") + " ", System.Drawing.Color.Blue);
}
}
private void ShowReceived2()
{
label2.Text = port2.BytesToRead.ToString();
for (int l = port2.BytesToRead; l > 0; l--)
{
ColoredTerminal(rtbTerminal2, port2.ReadByte().ToString("X") + " ", System.Drawing.Color.Blue);
}
}
private void ColoredTerminal(System.Windows.Forms.RichTextBox RichTextBox, string Text, System.Drawing.Color Color)
{
var StartIndex = RichTextBox.TextLength;
RichTextBox.AppendText(Text);
var EndIndex = RichTextBox.TextLength;
RichTextBox.Select(StartIndex, EndIndex - StartIndex);
RichTextBox.SelectionColor = Color;
RichTextBox.ScrollToCaret();
}
void Ustawienia_Enter(object sender, EventArgs e)
{
this.cbName1.Items.Clear();
this.cbName2.Items.Clear();
this.cbParity.Items.Clear();
this.cbStop.Items.Clear();
foreach (String s in SerialPort.GetPortNames()) this.cbName1.Items.Add(s);
foreach (String s in SerialPort.GetPortNames()) this.cbName2.Items.Add(s);
foreach (String s in Enum.GetNames(typeof(Parity))) this.cbParity.Items.Add(s);
foreach (String s in Enum.GetNames(typeof(StopBits))) this.cbStop.Items.Add(s);
cbName1.Text = port1.PortName.ToString();
cbName2.Text = port2.PortName.ToString();
cbBaud.Text = port1.BaudRate.ToString();
cbData.Text = port1.DataBits.ToString();
cbParity.Text = port1.Parity.ToString();
cbStop.Text = port1.StopBits.ToString();
}
void ButSendClick(object sender, EventArgs e)
{
if (port1.IsOpen)
{
Random rnd = new Random();
for (int i = 0; i <= 1000; i++)
{
int num = rnd.Next(0,255);
string hexString = num.ToString("X2");
ColoredTerminal(rtbTerminal1, hexString + " ", System.Drawing.Color.Black);
Byte[] tosend = BitConverter.GetBytes(num);
port1.Write(tosend, 0, 1);
}
}
else System.Windows.Forms.MessageBox.Show("Make connection first");
}
void TabPage1Click(object sender, EventArgs e)
{
}
void Label1Click(object sender, EventArgs e)
{
}
void Label3Click(object sender, EventArgs e)
{
}
void Label4Click(object sender, EventArgs e)
{
}
void ButDefault(object sender, EventArgs e)
{
}
void CbNameSelectedIndexChanged(object sender, EventArgs e)
{
}
void CbBaudSelectedIndexChanged(object sender, EventArgs e)
{
}
void RtbTerminalTextChanged(object sender, EventArgs e)
{
}
void ButRefreshClick(object sender, EventArgs e)
{
}
void ButDefaultClick(object sender, EventArgs e)
{
this.cbName1.Text = "COM3";
this.cbName2.Text = "COM4";
this.cbBaud.Text = "9600";
this.cbData.Text = "8";
this.cbParity.Text = "None";
this.cbStop.Text = "One";
}
void ButCancelClick(object sender, EventArgs e)
{
cbName1.Text = port1.PortName.ToString();
cbName2.Text = port2.PortName.ToString();
cbBaud.Text = port1.BaudRate.ToString();
cbData.Text = port1.DataBits.ToString();
cbParity.Text = port1.Parity.ToString();
cbStop.Text = port1.StopBits.ToString();
}
void PbStatus1Click(object sender, EventArgs e)
{
if (port1.IsOpen)
{
pbStatus1.BackColor = System.Drawing.Color.Red;
port1.Close();
labStatus1.Text = "No connection";
ColoredTerminal(rtbTerminal1, "\nConnection end - " + port1.PortName + "\n", System.Drawing.Color.Orange);
}
else
{
try
{
port1.PortName = this.cbName1.Text;
port1.BaudRate = Int32.Parse(this.cbBaud.Text);
port1.DataBits = Int32.Parse(this.cbData.Text);
port1.Parity = (Parity)Enum.Parse(typeof(Parity), this.cbParity.Text);
port1.StopBits = (StopBits)Enum.Parse(typeof(StopBits), this.cbStop.Text);
port1.Open();
pbStatus1.BackColor = System.Drawing.Color.Green;
labStatus1.Text = "Active connection (port:" + port1.PortName.ToString() + ", speed: " + port1.BaudRate.ToString() + ", data bits: " +
port1.DataBits.ToString() + "\n stop bits: " + port1.StopBits.ToString() + ", parity: " + port1.Parity.ToString() + ")";
ColoredTerminal(rtbTerminal1, "Connection started - " + port1.PortName + "\n", System.Drawing.Color.Orange);
}
catch(Exception exc)
{
MessageBox.Show("Connection error:\n" + exc.Message);
}
}
}
void PbStatus2Click(object sender, EventArgs e)
{
if (port2.IsOpen)
{
pbStatus2.BackColor = System.Drawing.Color.Red;
port2.Close();
labStatus2.Text = "No connection";
ColoredTerminal(rtbTerminal2, "\nConnection end - " + port2.PortName + "\n", System.Drawing.Color.Orange);
}
else
{
try
{
port2.PortName = this.cbName2.Text;
port1.BaudRate = Int32.Parse(this.cbBaud.Text);
port1.DataBits = Int32.Parse(this.cbData.Text);
port1.Parity = (Parity)Enum.Parse(typeof(Parity), this.cbParity.Text);
port1.StopBits = (StopBits)Enum.Parse(typeof(StopBits), this.cbStop.Text);
port2.Open();
pbStatus2.BackColor = System.Drawing.Color.Green;
labStatus2.Text = "Active connection (port:" + port2.PortName.ToString() + ", speed: " + port2.BaudRate.ToString() + ", data bits: " +
port2.DataBits.ToString() + "\n stop bits: " + port2.StopBits.ToString() + ", parity: " + port2.Parity.ToString() + ")";
ColoredTerminal(rtbTerminal2, "Connection started - " + port2.PortName + "\n", System.Drawing.Color.Orange);
}
catch(Exception exc)
{
MessageBox.Show("Connection error:\n" + exc.Message);
}
}
}
void LabStatusClick(object sender, EventArgs e)
{
}
void NumericSendValueChanged(object sender, EventArgs e)
{
}
void Label7Click(object sender, EventArgs e)
{
}
}
}
What I have tried:
I tried to deal with "for" loop. The only situation when I see receiving chars in parallel to sended chars ("one by one") is when after line...
port1.Write(tosend, 0, 1);
...I add
rtbTerminal2.Invoke(moj_del2);
...but it is not the right way to force receiving particulary bytes.
Best regards
Karlsson