Unfortunately waiting for a serial port data in C# is tricky, there is nothing like poll()
.
There is SerialPort.DataReceived
which takes functions to be called on incoming data. So you assign there a function to trigger an arbitrary event. Your another function — the one to actually wait — should wait for this event.
Below is a simple example, it is commented, but in short: the TestFunc
initializes and opens a serial port (in particular assigns the DataReceived
). The Proxy()
is a function that will be called every time a data arrived, it triggers an event. And WaitForAData()
indeed waits for the event that will be triggered by Proxy()
when a data appears. Note the lock(){}
s, without them surrounding Monitor
's functions it won't work properly.
It's just an example, you would probably want to remake WaitForAData()
function to trigger an exception in case of timeout. And to add a boolean variable in case if the Proxy()
was triggered before you began waiting, then serial port already have data. But I tested it (cause I need such a function now ☺), and it works.
namespace MyNamespace
{
class MySerial
{
///A condition variable that signals when serial has a data
private System.Object SerialIncoming;
public MySerial()
{
SerialIncoming = new Object();
}
/**
* A proxy function that will be called every time a data arrived
*/
private void Proxy(Object unused1, SerialDataReceivedEventArgs unused2)
{
Console.WriteLine("Data arrived!");
lock (SerialIncoming)
{
Monitor.Pulse(SerialIncoming);
}
}
/**
* Waits for a data for the time interval Timeout
* \param Timeout a timeout in milliseconds to wait for a data
* \returns true in if a data did arrived, and false else
*/
public bool WaitForAData(int Timeout)
{
lock (SerialIncoming)//waits N seconds for a condition variable
{
if (!Monitor.Wait(SerialIncoming, Timeout))
{//if timeout
Console.WriteLine("Time out");
return false;
}
return true;
}
}
/* Just a test function: opens a serial with speed, and waits
* for a data for the «Timeout» milliseconds.
*/
public void TestFunc(string serial, int speed, int Timeout)
{
SerialPort ser = new SerialPort(serial);
ser.BaudRate = speed;
ser.DataReceived += Proxy;
ser.Open();
if (WaitForAData(Timeout))
Console.WriteLine("Okay in TestFunc");
else
Console.WriteLine("Time out in TestFunc");
}
}
}
UPDATE: the problem wasted ½ of my day, so I hope I will save someone's time: the code above won't work in mono (but works in MS implementation) because serial port events are not supported as of writing these words.