C# read Data from 2 RS232(COM-Ports) independent - c#

Is there any possibility to read Data from 2 RS232 Ports parallel?
It seems, that when i have 2 DataReceived-Events there are blocking each other.
I have also tried to set the SerialPort.ReceivedBytesThreshold to a value of 50/100
class DataCollector
{
private SerialPort _serialPort;
List<String> Data;
private bool _finished = false;
private bool _handshake = true;
public DataCollector(SerialPort serialPort, bool handshake=true)
{
Data = new List<String>();
_serialPort = serialPort;
_serialPort.DataReceived += SerialPortDataReceived;
_handshake = handshake;
if (_serialPort.IsOpen)
{
_serialPort.DiscardInBuffer();
}
}
~DataCollector()
{
if (_serialPort.IsOpen)
{
_serialPort.DiscardInBuffer();
}
Data.Clear();
}
private void SerialPortDataReceived(object sender, SerialDataReceivedEventArgs e)
{
if (_handshake == false)
{
String str =_serialPort.ReadLine();
str.Insert(str.Length, "\n");
Data.Add(str);
if (Data.Count == 48)
{
_finished = true;
}
}
else
{
Char readedByte = (char)_serialPort.ReadByte();
if ((readedByte != (char)5) && Data.Count == 0)
{
return;
}
if (readedByte.CompareTo((char)2) == 0)
{
readLine();
sendAck();
}
else if (readedByte.CompareTo((char)5) == 0)
{
Data.Add(((char)5).ToString());
sendAck();
}
else if (readedByte == (char)4)
{
_finished = true;
}
}
private void sendAck()
{
if (_serialPort.IsOpen )
{
Byte[] bytes = {6};
_serialPort.Write(bytes,0,1);
}
}
private void readLine(){
String str = _serialPort.ReadLine();
Data.Add(str);
}
}
There are 2 defined in the Main:
_inputCollector = new DataCollector(_RS232Input);
_inputSecondCollector = new DataCollector(_RS232SecondInput, false);

Comment
I would seriously reconsider that implementation of only having a single thread - you should realistically have two separate threads each dealing with its own serial port (as currently, the program will 'freeze' if a large message was passed in - meaning the second port will be 'unusable' until this msg has finished).
Answer
Your system is currently running on a single thread. But implementing a muti-threading system - one which will listen to the first port, and another to listen to the second port. That way, they can both work at the same time.
Currently, (on this single thread) if data is received on one port, (and the other receives also) the thread will 'freeze' until the first message has been received/dealt with - and THEN will read the second port (that is, if it has not already timed out). So by using two threads, both ports can be written/read simultaneously (or, seem to be anyway).

Related

Concurrent queue is not dequeued/cleared

My requirement is to insert item in a queue and process it but the items should be added first and after a while they should be processed (as some other things needs to be set before processing the items. Here is the coding I have done so far.
#region Variables Declarations
private Thread threadTask = null;
ConcurrentQueue<string> concurrentQueue = new ConcurrentQueue<string>();
string currentSeqNo;
string previousSeqNo = "-1";
#endregion
private void test1_Load(object sender, EventArgs e)
{
AddItems();
if (threadTask == null)
{
threadTask = new Thread(Kick);
Thread.Sleep(5000);
threadTask.Start();
}
}
private void AddItems()
{
for (Int64 i = 100000; i < 300000; i++)
{
concurrentQueue.Enqueue(i.ToString());
this.Invoke(new MethodInvoker(delegate()
{
label1.Text = i.ToString();
label1.Update();
}));
}
}
private void Kick()
{
while (true)
{
int recordCountNew = concurrentQueue.Count();
if (recordCountNew != 0)
{
RemoveItems();
}
}
}
private void RemoveItems()
{
string item;
while (concurrentQueue.TryDequeue(out item))
{
this.Invoke(new MethodInvoker(delegate()
{
label2.Text = item;
label2.Update();
}));
currentSeqNo = item; // second time does not start wil 100000
if (previousSeqNo != "-1")
{
if (long.Parse(currentSeqNo) != long.Parse(previousSeqNo) + 1)
{
Reconnect();
}
else
{
//Process item
previousSeqNo = currentSeqNo;
}
}
else
{
//Process item
previousSeqNo = currentSeqNo;
}
}
}
private void Reconnect()
{
currentSeqNo = "";
previousSeqNo = "-1";
string someItem;
while (concurrentQueue.Count > 0)
{
concurrentQueue.TryDequeue(out someItem);
}
this.Invoke(new MethodInvoker(delegate()
{
label1.Text = "";
label2.Text = "";
label1.Update();
label2.Update();
}));
AddItems();
if (threadTask == null)
{
threadTask = new Thread(Kick);
threadTask.Start();
}
}
private void button1_Click_1(object sender, EventArgs e)
{
Reconnect();
}
To reproduce the issue: Run the app and in the middle click on the button. Now the queue should again be started from 100000 but it shows the number somewhere greater than 100000.
Please advise how do I release all the resources to make a fresh start after clicking a button. Though I am setting them to default and also clearing the queue but it still shows the old values in currentSeqNo when 'RemoveItems' method is called.
What you see is a race condition between the Kick thread and the button click handler. When you press the button you execute Reconnect() in it you clean the queue and then call the AddItems() function. But all this time the Kick function tries to Dequeue and so you end up each time with an arbitrary amount of items in it. What you should do is to synchronize between these functions or prevent the Kick from executing while you are adding items.
Couple of comments:
1) You Kick() method have an infinite loop, that too without sleep. Every thread started will keep on running as you didn't have a scope for thread to come out.
You can have a member variable like bKeepRunning with default value as true. Set that variable to false in beginning of Reconnect() function. Something like:
private void Kick()
{
while (bKeepRunning)
{
int recordCountNew = concurrentQueue.Count();
if (recordCountNew != 0)
{
RemoveItems();
}
}
}
Why do you have Thread.Sleep(5000); in test1_Load()? I dont think that is needed.
I made small change in your code, something like:
private void AddItems()
{
for (Int64 i = 100000; i < 300000; i++)
{
concurrentQueue.Enqueue(i.ToString());
this.Invoke(new MethodInvoker(delegate()
{
label1.Text = i.ToString();
label1.Update();
}));
if (i < 100004)
Thread.Sleep(1000);
}
}
private void Kick()
{
while (bKeepRunning)
{
int recordCountNew = concurrentQueue.Count();
if (recordCountNew != 0)
{
RemoveItems();
}
}
}
private void Reconnect()
{
currentSeqNo = "";
previousSeqNo = "-1";
bKeepRunning = false;
threadTask = null;
string someItem;
while (concurrentQueue.Count > 0)
{
concurrentQueue.TryDequeue(out someItem);
}
this.Invoke(new MethodInvoker(delegate()
{
label1.Text = "";
label2.Text = "";
label1.Update();
label2.Update();
}));
Thread.Sleep(2000);
AddItems();
bKeepRunning = true;
if (threadTask == null)
{
threadTask = new Thread(Kick);
threadTask.Start();
}
}
It helped me to see that value is starting from 100000. You can try the same at your end.
Note: I have stopped thread and restarted after clicking on button. Hence i dont see any flaw in your code as such. It just runs fast so that you are not able to realize start values.
You should make UI thread and threadTask thread sync, just use ManualResetEventSlim Signal Construct to, like this:
static ManualResetEventSlim guard = new ManualResetEventSlim(true);
private void button1_Click_1(object sender, EventArgs e)
{
guard.Reset();
Reconnect();
guard.Set();
}
private void RemoveItems()
{
string item;
while (concurrentQueue.TryDequeue(out item))
{
guard.Wait();
//......
}
}
see:
ManualResetEventSlim Class

thread safe read and write list

I am trying to use lock for read and write to list at the same time. I adding bytes from serial port to a list while processing these bytes by reading from same list with the help of lock. My problem is that while running it in debug mode it is working fine but while running normally it showing exception. Following is my code.
private void receiveData(object sender, SerialDataReceivedEventArgs e)
{
while (connectComPort.BytesToRead > 0)
receivedBytes1.Add((byte)connectComPort.ReadByte());
}
int tint = 0;
private static readonly object _object = new object();
private void modprocessReceivedBuffer()
{
while (1 == 1)
{
try
{
if (receivedBytes1.Count() > tint)
{
List<byte> receivedBytes12 = null;
lock (_object)
{
receivedBytes12 = receivedBytes1.GetRange(tint, 2).ToList<byte>(); //LINE 1
}
if (receivedBytes12[0] == 0x0D)
{
if (receivedBytes12[1] == 0xAF)
{
try
{
var tiff = receivedBytes1.GetRange(tint, ((int)receivedBytes1[tint + 4])).ToList<byte>();
tint += (int)receivedBytes1[tint + 4];
modifiedProcess(tiff);
if (receivedBytes1.Count() == tint)
{
receivedBytes1.Clear();
tint = 0;
Thread.Sleep(20);
}
}
catch
{
}
}
}
else
{
tint += 1;
}
}
}
catch (Exception ex)
{
Log.Error("bug : " + ex.ToString());
}
}
}
Line 1 shows "System.ArgumentException: Offset and length were out of bounds for the array or count is greater than the number of elements from index to the end of the source collection" while running the code normally. I am not able to catch this error while running in debug mode. My second question is that if their is any thread safe list like structure in c#?
I would also like to add that I am receiving data from port at a very fast rate 16000 bytes/sec average.

C# BackgroundWorker Completed Called Way Before Completion

I have been trying to work out why my background worker is 'finishing' its work when there is still a lot for it to do. I am actually in the process of refactoring the code for this app, so it did work in the past, but now I am unable to figure out what has gone wrong.
Specifically, the app should open Outlook and then perform a few checks. However, the background worker exits straight after Outlook is opened for no apparent reason (as you will se below there is still plenty of processing to be done).
This appears to be happening early on in the Start() method, directly after calling Process.Start() on Outlook.exe.
The code runs in this order:
calling the background worker - this was the user's choice from a radio set
....
else if (radioButton5.Checked == true)
{
textBox1.Text = "Please wait while your session restarts";
pageControl1.SelectedIndex = 10;
backgroundReset.RunWorkerAsync();
}
The do-work method
public void backgroundReset_DoWork(object sender, DoWorkEventArgs e)
{
backgroundReset.WorkerSupportsCancellation = true;
Session.Reset();
}
the reset session method starts by killing the current session ...
public static void Reset()
{
KillSession();
System.Threading.Thread.Sleep(5000);
Start();
// THE BACKGROUNDWORKER EXITS BEFORE HERE!
if (IsLoggedIn() == false)
{
return;
}
else
{
// Make sure Lync is open before finishing the process ...
var j = 0;
GetSession(Init.servers);
j = 0;
var checker = false;
checker = ProcessHandler.CheckRunning("lync.exe");
while (checker == false)
{
if (j == 100)
{
break;
}
Thread.Sleep(500);
checker = ProcessHandler.CheckRunning("lync.exe");
j++;
}
}
}
As you can see from the comment, the backgroundworder is calling RunWorkerCompleted way before the Reset() method has finished executing.
Below are the other methods called (kill, logoff, start):
KillSession logs the session of and then makes sure it is logged off
private static void KillSession()
{
if (sessionId != null)
{
LogOff();
for (int i = 0; i < 150; i++)
{
if (IsLoggedIn() == true)
{
Thread.Sleep(500);
}
else
{
break;
}
}
}
}
LogOff sends a Cmd command to log off the current session
public static void LogOff()
{
string strCmdIn = "/C LOGOFF " + sessionId + " /SERVER:" + serverName;
Cmd.Exec(strCmdIn);
}
Start() Simply opens Outlook, causing a Citrix session to also start. The app is definitely launching Outlook, but after that it doesn't reach either of the for statements - the BackgroundWorker just exits.
public static void Start()
{
Process.Start(appDataCitrix + "Outlook.exe");
for (int i = 0; i < 15; i++)
{
if (IsLoggedIn2() == false)
{
Thread.Sleep(1000);
}
else
{
break;
}
}
if (IsLoggedIn2() == false)
{
Process.Start(appDataCitrix + "Outlook.exe");
for (int i = 0; i < 10; i++)
{
if (IsLoggedIn2() == false)
{
Thread.Sleep(1000);
}
else
{
break;
}
}
}
}
Does anyone have any idea what is going on here? It is driving me crazy!
Many thanks
Update
The RunWorkerCompleted Method:
As far as my understanding goes, this has no baring on when the process will finish.
public void backgroundReset_RunWorkerCompleted(object sender, RunWorkerCompletedEventArgs e)
{
if (Session.IsLoggedIn())
{
btnFailFinish.Visible = true;
label10.Text = Session.serverName;
pageControl1.SelectedIndex = 3;
}
else
{
pageControl1.SelectedIndex = 10;
pictureBox2.Visible = false;
textBox1.Text = "Double-click Outlook on your desktop to launch a new session.";
textBox15.Text = "Once you have done this please click Finish.";
pictureBox9.Visible = true;
}
}
This is probably because of an exception being thrown from within the start method.
You may either add a try / catch block all around this method and handle the error from within the catch, or check in the RunWorkerCompleted method if an exception occurred :
private void RunWorkerCompleted (object sender, RunWorkerCompletedEventArgs e)
{
if (e.Error != null)
{
// handle your exception here
}
}

Performance counter CPU usage for current process is more than 100

I want to display CPU usage for my multithread application (working over multicore processor). I want to receive numbers close to Task manager's. But I got numbers more than 100%. Even more than 500%. Yes, I know, than counter "% Processor Time" for category "Process" I need to divide into Environment.ProcessorCount or "NumberOfLogicalProcessors" (same for my configuration). And 500% is a result after this operation. I tested this example on different computers with different hardware (i7, i5, Core2) and software configurations (Windows 7 SP1 with all updates, Windows 2008 R2 SP1 with all updates) and got same problem.
public static class SystemInfo
{
private static Process _thisProc;
private static bool HasData = false;
private static PerformanceCounter _processTimeCounter;
private static void Init()
{
if (HasData)
return;
if (CheckForPerformanceCounterCategoryExist("Process"))
{
_processTimeCounter = new PerformanceCounter();
_processTimeCounter.CategoryName = "Process";
_processTimeCounter.CounterName = "% Processor Time";
_processTimeCounter.InstanceName = FindInstanceName("Process");
_processTimeCounter.NextValue();
}
MaximumCpuUsageForCurrentProcess = 0;
HasData = true;
}
private static bool CheckForPerformanceCounterCategoryExist(string categoryName)
{
return PerformanceCounterCategory.Exists(categoryName);
}
public static string FindInstanceName(string categoryName)
{
string result = String.Empty;
_thisProc = Process.GetCurrentProcess();
if (!ReferenceEquals(_thisProc, null))
{
if (!String.IsNullOrEmpty(categoryName))
{
if (CheckForPerformanceCounterCategoryExist(categoryName))
{
PerformanceCounterCategory category = new PerformanceCounterCategory(categoryName);
string[] instances = category.GetInstanceNames();
string processName = _thisProc.ProcessName;
if (instances != null)
{
foreach (string instance in instances)
{
if (instance.ToLower().Equals(processName.ToLower()))
{
result = instance;
break;
}
}
}
}
}
}
return result;
}
public static int CpuUsageForCurrentProcess
{
get
{
Init();
if (!ReferenceEquals(_processTimeCounter, null))
{
int result = (int) _processTimeCounter.NextValue();
result /= Environment.ProcessorCount; //NumberOfLogicalProcessors //same for me
if (MaximumCpuUsageForCurrentProcess < result)
MaximumCpuUsageForCurrentProcess = result;
return result;
}
return 0;
}
}
public static int MaximumCpuUsageForCurrentProcess { private set; get; }
}
and code to execute (you need to create windows forms application with two labeles, one BackgroundWorker and one button)
private void backgroundWorker1_DoWork(object sender, DoWorkEventArgs e)
{
IList<Task> tasks = new List<Task>();
for (int i = 0; i < 10; i++)
{
Task t = new Task(() =>
{
do {
if (backgroundWorker1.CancellationPending)
break;
} while (true);
});
t.Start();
tasks.Add(t);
}
Task displayProgress = new Task(() => { do {
if (backgroundWorker1.CancellationPending)
break;
backgroundWorker1.ReportProgress(1);
Thread.Sleep(10);
} while (true); });
displayProgress.Start();
tasks.Add(displayProgress);
Task.WaitAll(tasks.ToArray());
}
private void backgroundWorker1_ProgressChanged(object sender, ProgressChangedEventArgs e)
{
label1.Text = SystemInfo.CpuUsageForCurrentProcess.ToString();
label2.Text = SystemInfo.MaximumCpuUsageForCurrentProcess.ToString();
}
private void button1_Click(object sender, EventArgs e)
{
label1.Text = SystemInfo.CpuUsageForCurrentProcess.ToString();
if (backgroundWorker1.IsBusy)
backgroundWorker1.CancelAsync();
else
backgroundWorker1.RunWorkerAsync();
}
Please show me my error. And yes, I read this article and noticed that
“\Process(…)\% Processor Time” can go up to N*100 (where N is the number of CPUs) because it adds up the CPU usage of the requested process across all the CPUs.
This (somewhat related) question suggests using the System.Diagnostics.Process.TotalProcessorTime and System.Diagnostics.ProcessThread.TotalProcessorTime properties instead, for low overhead and easy implementation.
(Edit: Here's an article explaining how to use the properties, as well.)
Also, it looks like you're not waiting long enough between calls to "_processTimeCounter.NextValue()." As per the documentation, you're supposed to wait at least 1 second. Not sure if that would cause your strange numbers or not.

Serial Port In C#

I am working with a program the reads data from a file and plots it to a graph in real time. My stream is coming from a microcontroller output and I am building an interface to display the data. I am using stream reader in my routine, but I have a problem.
I have decided to use the data from the serial port directly. I get an error when I try to use the variable line that I have just read from the port. I do not know what I am doing wrong.
Thanks.
int tickStart = 0;
System.IO.Ports.SerialPort port;
public string portname;
public Parity parity;
public int BaudRate;
public StopBits stopbits;
public int databits;
int count;
String line;
public string PortName
{
get { return portname; }
set { portname = value; }
}
private void Form1_Load( object sender, EventArgs e )
{
//graphing stuff
count = 0;
portname = "COM1";
parity = Parity.None;
BaudRate = 9600;
stopbits = StopBits.Two;
databits = 8;
port = new System.IO.Ports.SerialPort(portname);
port.Parity = parity;
port.BaudRate = BaudRate;
port.StopBits = stopbits;
port.DataBits = databits;
port.DataReceived += new SerialDataReceivedEventHandler(port_DataReceived);
port.Open();
count = 0;
}
void port_DataReceived(object sender, SerialDataReceivedEventArgs e)
{
try
{
line = port.ReadLine();
count++;
}
catch (Exception ex)
{
MessageBox.Show(ex.Message);
}
}
private void timer1_Tick( object sender, EventArgs e )
{
//graphing stuff
if (list == null)
return;
// Time is measured in seconds
double time = (Environment.TickCount - tickStart) / 1000.0;
double value = double.Parse(line);
list.Add(time, value);
//graphing stuff
}
in timer1_Tick, add an additional check for 'line == null', in addition to 'list == null'.
Assuming that your data comes in no more often than the firing rate of your timer, and, that the data received arrives all in one burst.
If I understand correctly, what happens is that the timer ticks before a value has been read from the port for the first time. This means that line == null still, so you get the error.
The best solution would be to not start the timer before at least one line is read, but checking for null would also do the trick.

Categories

Resources