/// <summary> /// Send and receive serial communication asynchronously. /// </summary> /// <param name="cmd">Send command</param> /// <remarks> /// [Note] /// If you let the UI thread process while receiving data, data is likely to be missed. /// Data is sent and received in order using the command response method. /// 1.Send command from form /// -> 2.Send and receive command in thread /// -> 3.Write received data on form /// </remarks> async private void AsyncSerialPort(byte cmd) { // Clear the log area every 1000 times. if (this._normalCount % 1000 == 0) { this.txtLog.Clear(); } // Get send command from definition list. this._lastSendCommandID = cmd; TOFCommand command = this.GetCommand(cmd); this._serialPort.ReceivedDataLength = 0; // Write send command information to log area. this.txtLog.AppendText(string.Format("{0} {1} {2} {3}\r\n" , DateTime.Now.ToString("HH:mm:ss.fff") , command.SendDataLength.ToString("D7") , "Send " , BitConverter.ToString(command.SendData))); this.txtLog.ScrollToCaret(); // Send send command to serial port asynchronously. await Task.Run(() => this._serialPort.SendReceive(command)); // When called back, write the received data. this.CallbackSerialPort(); }
/// <summary> /// Send Command And Wait for Receive Response /// </summary> /// <param name="command">Command class object</param> public void SendReceive(TOFCommand command) { // Set command from parameter. this._command = command; // Set the flag to True to start sending and receiving. this._isSendingReceiving = true; // Wait until sending and receiving stops. while (this._isSendingReceiving) { Thread.Yield(); } }
/// <summary> /// Callback processing after receiving data. /// </summary> /// <remarks> /// </remarks> private void CallbackSerialPort() { byte[] data = this._serialPort.ReceiveDataBuffer; int length = this._serialPort.ReceivedDataLength; bool isError = this._serialPort.IsError; try { if (6 <= length && data[0] == 0xFE) { // When the synchronization code is 0xFE and the received data length is 6 or more. int dataLength = (data[2] << 24) + (data[3] << 16) + (data[4] << 8) + data[5]; if (length == dataLength + 6) { // When all data can be received, // Write received data information to log area. this._normalCount++; this.txtResult.Text = string.Format("Nromal count:{0}. Error count:{1}.", this._normalCount.ToString(), this._errorCount.ToString()); this.txtLog.AppendText(string.Format("{0} {1} {2} {3}\r\n" , DateTime.Now.ToString("HH:mm:ss.fff") , length.ToString("D7") , "Receive" , BitConverter.ToString(data, 0, 20 <= length ? 20 : length))); this.txtLog.ScrollToCaret(); // If Output CSV is TRUE, CSV output. if (this._lastSendCommandID == 0x82 && this.chkOutputCSV.Checked) { // Get command definition. TOFCommand command = this.GetCommand(this._lastSendCommandID); // Extract get result data from the receive buffer. byte[] resultData = new byte[command.ReceiveDataLength]; Buffer.BlockCopy(data, 0, resultData, 0, length); // CSV output. this.OutputCsv(resultData); } // If Repeat is TRUE, Send Get result command. if (this.chkRepeat.Checked) { this.AsyncSerialPort(this._lastSendCommandID); return; } } else { // When some data could not be received, // Write received data information to log area. this._errorCount++; this.txtLog.AppendText(string.Format("Failed to receive data. The received data length is {0} bytes.\r\n" , length)); this.txtLog.ScrollToCaret(); // If Repeat is TRUE, Send Get result command. if (this.chkRepeat.Checked) { this.AsyncSerialPort(this._lastSendCommandID); return; } } } else { // When some data could not be received, // Write received data information to log area. this._errorCount++; if (isError) { // When some data could not be received, // Write received data information to log area. this.txtLog.AppendText(string.Format("Failed to send data.\r\n")); } else { // When some data could not be received, // Write received data information to log area. this.txtLog.AppendText(string.Format("Failed to receive data.\r\n")); } this.txtLog.ScrollToCaret(); // If Repeat is TRUE, Send Get result command. if (this.chkRepeat.Checked) { this.AsyncSerialPort(this._lastSendCommandID); return; } } } catch (ObjectDisposedException) { // Do nothing until the object is destroyed. } }