I'd guess that the Main loop is spinning, preventing the event from firing. Add a Thread.Sleep(10) in your Main while (true) loop to give the event queue a little breathing room.
The .NET event is similar to the Arduino interrupt, the big difference is the event is queued and processed in the same thread as the event source and interrupts are much more immediate. Since the _port is running in the main thread, the light loop in Main isn't yielding to let the event fire.
Should i Open the SerialPort in a separate Thread?
I get the events, Its just that when im parsing data in the ParseData method, i seem to loose data. I sent a 100 Line txt document to the serial port as quick as 9600 will let me. During the send into the netduino, i loose data. it seems that when i read from the string "Message", line get cut out. I'm guessing the reason is because of threads and when one is writing the string , another is removing data, and parts get lost???? During my parseData method, i need to check the SD card if certain data exists, Maybe this slows down the netduino to the point where my data is messed up?
Is there any Serialport that exists that can read line by line without data loss not matter how long the parse method takes?
I found this "Extension" to the SerialPort... But During the Parse, i still lose lines....
public class SimpleSerial : System.IO.Ports.SerialPort{ // CONSTRUCTORS -- Pass the Buck public SimpleSerial(string portName, int baudRate, System.IO.Ports.Parity parity, int dataBits, System.IO.Ports.StopBits stopBits) : base(portName, baudRate, parity, dataBits, stopBits) { } public SimpleSerial(string portName, int baudRate, System.IO.Ports.Parity parity, int dataBits) : base(portName, baudRate, parity, dataBits) { } public SimpleSerial(string portName, int baudRate, System.IO.Ports.Parity parity) : base(portName, baudRate, parity) { } public SimpleSerial(string portName, int baudRate) : base(portName, baudRate) { } public SimpleSerial(string portName) : base(portName) { } /// <summary> /// Writes the specified string to the serial port. /// </summary> /// <param name="txt"></param> public void Write(string txt) { base.Write(Encoding.UTF8.GetBytes(txt), 0, txt.Length); } /// <summary> /// Writes the specified string and the NewLine value to the output buffer. /// </summary> /// <param name="txt"></param> public void WriteLine(string txt) { this.Write(txt + "rn"); } /// <summary> /// Reads all immediately available bytes, as binary data, in both the stream and the input buffer of the SerialPort object. /// </summary> /// <returns>byte[]</returns> public byte[] ReadExistingBinary() { int arraySize = this.BytesToRead; byte[] received = new byte[arraySize]; this.Read(received, 0, arraySize); return received; } /// <summary> /// Reads all immediately available bytes, based on the encoding, in both the stream and the input buffer of the SerialPort object. /// </summary> /// <returns>String</returns> public string ReadExisting() { try { return new string(Encoding.UTF8.GetChars(this.ReadExistingBinary())); } catch (Exception) { return string.Empty; } } /// <summary> /// Opens a new serial port connection. /// </summary> public new void Open() { this._Remainder = string.Empty; // clear the remainder so it doesn't get mixed with data from the new session base.Open(); } /// <summary> /// Stores any incomplete message that hasn't yet been terminated with a delimiter. /// This will be concatenated with new data from the next DataReceived event to (hopefully) form a complete message. /// This property is only populated after the Deserialize() method has been called. /// </summary> private string _Remainder = string.Empty; public string Remainder { get { return this._Remainder; } } /// <summary> /// Splits data from a serial buffer into separate messages, provided that each message is delimited by one or more end-of-line character(s). /// </summary> /// <param name="delimiter">Character sequence that terminates a message line. Default is "rn".</param> /// <returns> /// An array of strings whose items correspond to individual messages, without the delimiters. /// Only complete, properly terminated messages are included. Incomplete message fragments are saved to be appended to /// the next received data. /// /// If no complete messages are found in the serial buffer, the output array will be empty with Length = 0. /// </returns> public string[] Deserialize(string delimiter = "rn") { string receivedData = string.Concat(this._Remainder, this.ReadExisting()); // attach the previous remainder to the new data return SplitString(receivedData, out this._Remainder, delimiter); // return itemized messages and store remainder for next pass } /// <summary> /// Splits a stream into separate lines, given a delimiter. /// </summary> /// <param name="input"> /// The string that will be deserialized. /// /// Example: /// Assume a device transmits serial messages, and each message is separated by rn (carriage return + line feed). /// /// For illustration, picture the following output from such a device: /// First message.rn /// Second message.rn /// Third message.rn /// Fourth message.rn /// /// Once a SerialPort object receives the first bytes, the DataReceived event will be fired, /// and the interrupt handler may read a string from the serial buffer like so: /// "First message.rnSecond message.rnThird message.rnFourth me" /// /// The message above has been cut off to simulate the DataReceived event being fired before the sender has finished /// transmitting all messages (the "ssage.rn" characters have not yet traveled down the wire, so to speak). /// At the moment the DataReceived event is fired, the interrupt handler only has access to the (truncated) /// input message above. /// /// In this example, the string from the serial buffer will be the input to this method. /// </param> /// <param name="remainder"> /// Any incomplete messages that have not yet been properly terminated will be returned via this output parameter. /// In the above example, this parameter will return "Fourth me". Ideally, this output parameter will be appended to the next /// transmission to reconstruct the next complete message. /// </param> /// <param name="delimiter"> /// A string specifying the delimiter between messages. /// If omitted, this defaults to "rn" (carriage return + line feed). /// </param> /// <param name="includeDelimiterInOutput"> /// Determines whether each item in the output array will include the specified delimiter. /// If True, the delimiter will be included at the end of each string in the output array. /// If False (default), the delimiter will be excluded from the output strings. /// </param> /// <returns> /// string[] /// Every item in this string array will be an individual, complete message. The first element /// in the array corresponds to the first message, and so forth. The length of the array will be equal to the number of /// complete messages extracted from the input string. /// /// From the above example, if includeDelimiterInOutput == True, this output will be: /// output[0] = "First message.rn" /// output[1] = "Second message.rn" /// output[2] = "Third message.rn" /// /// If no complete messages have been received, the output array will be empty with Length = 0. /// </returns> private static string[] SplitString(string input, out string remainder, string delimiter = "rn", bool includeDelimiterInOutput = false) { string[] prelimOutput = input.Split(delimiter.ToCharArray()); // Check last element of prelimOutput to determine if it was a delimiter. // We know that the last element was a delimiter if the string.Split() method makes it empty. if (prelimOutput[prelimOutput.Length - 1] == string.Empty) remainder = string.Empty; // input string terminated in a delimiter, so there is no remainder else { remainder = prelimOutput[prelimOutput.Length - 1]; // store the remainder prelimOutput[prelimOutput.Length - 1] = string.Empty; // remove the remainder string from prelimOutput to avoid redundancy } if (includeDelimiterInOutput == true) return ScrubStringArray(prelimOutput, removeString: string.Empty, delimiter: delimiter); else return ScrubStringArray(prelimOutput, removeString: string.Empty, delimiter: string.Empty); } /// <summary> /// Removes items in an input array that are equal to a specified string. /// </summary> /// <param name="input">String array to scrub.</param> /// <param name="removeString">String whose occurrences will be removed if an item consists of it. Default: string.Empty.</param> /// <param name="delimiter"> /// Delimiter that will be appended to the end of each element in the output array. Default: rn (carriage return + line feed). /// To omit delimiters from the end of each message, set this parameter to string.Empty. /// </param> /// <returns> /// String array containing only desired strings. The length of this output will likely be shorter than the input array. /// </returns> private static string[] ScrubStringArray(string[] input, string removeString = "", string delimiter = "rn") { // Note: I originally wanted to use a System.Collections.ArrayList object here and then run the ToArray() method, // but the compiler throws runtime exceptions for some reason, so I've resorted to this manual array-copying approach instead. int numOutputElements = 0; // Determine the bounds of the output array by looking for input elements that meet inclusion criterion for (int k = 0; k < input.Length; k++) { if (input[k] != removeString) numOutputElements++; } // Declare and populate output array string[] output = new string[numOutputElements]; int m = 0; // output index for (int k = 0; k < input.Length; k++) { if (input[k] != removeString) { output[m] = input[k] + delimiter; m++; } } return output; }