MTSkull
Centurion
I am having a serial issue and may need counseling if I do not get it fixed soon.
I am writing a process to communicate with a device serially. The command button procedure calls 4 different sub procedures that communicate with the device. Each sub procedure opens writes to/reads from the device. Then closes and disposes of the device. I encapsulated the serial function in a class. As the program is running it will periodically error out with a The I/O operation has been aborted because of either a thread exit or application request. error. Additionally if I run it in the IDE it is more reliable then running it from the exe.
When it runs in the sub routine it will initialize and open just fine but then on the first read or write it crashes. Usually the first sub routine will be okay but subsequent ones will fail.
Things I have tried so far..
1. I declared the serial class in the command button procedure and then passed it as a parameter to the sub routines. This also produced errors.
2. Created a simple form to emulate the functions as well as passing to the functions as parameters. This worked fine.
3. Called GC.Collect(); at the end of every function to try and get it to clean up after itself. Did not work.
4. I am going to try implementing it without the class and just use the serial commands directly in the functions. I would however like to have this in a class as I intend to use this in more places once it Is working.
Thanks MT
--EDIT: this is in c# 2005 in case you didn't guess. MT
Here is the class.
I am writing a process to communicate with a device serially. The command button procedure calls 4 different sub procedures that communicate with the device. Each sub procedure opens writes to/reads from the device. Then closes and disposes of the device. I encapsulated the serial function in a class. As the program is running it will periodically error out with a The I/O operation has been aborted because of either a thread exit or application request. error. Additionally if I run it in the IDE it is more reliable then running it from the exe.
When it runs in the sub routine it will initialize and open just fine but then on the first read or write it crashes. Usually the first sub routine will be okay but subsequent ones will fail.
Things I have tried so far..
1. I declared the serial class in the command button procedure and then passed it as a parameter to the sub routines. This also produced errors.
2. Created a simple form to emulate the functions as well as passing to the functions as parameters. This worked fine.
3. Called GC.Collect(); at the end of every function to try and get it to clean up after itself. Did not work.
4. I am going to try implementing it without the class and just use the serial commands directly in the functions. I would however like to have this in a class as I intend to use this in more places once it Is working.
Thanks MT
--EDIT: this is in c# 2005 in case you didn't guess. MT
Here is the class.
C#:
using System;
using System.Collections.Generic;
using System.IO.Ports;
using System.Text;
using System.Windows.Forms;
using System.Threading;
namespace FGRIO_Slave_Cal
{
class SimpleSerialComm: IDisposable
{
#region Notes
// This class provides very basic serial port read and write capabilities
// Created 08/18/06 MTSkull
#endregion
#region Variables
private string CommPort = "COM1";
private Int32 Baud = 19200;
SerialPort LocalPort = null;
public char Escape = (char)27;
public char Enter = (char)13;
//trouble shooting vars
private bool Constructor = false;
private bool PortOpen = false;
private bool disposed = false;
#endregion
#region Constructor/Destructor/Dispose
public SimpleSerialComm(string CommPortIn, Int32 BaudIn)//constructor
{
CommPort = CommPortIn;
Baud = BaudIn;
Constructor = true;
}
~SimpleSerialComm()//destructor
{
Dispose(false);
}
public void Dispose()//public dispose
{
Dispose(true);
GC.SuppressFinalize(this);
}
protected virtual void Dispose(bool disposing)//private dispose, work actually happens here
{
if (!this.disposed)
{
if (disposing)
{
LocalPort.Dispose();
}
}
disposed = true;
}
#endregion
#region Variable Set/Get Procedures
public void SetCommPort(string NewCommPort)
{
CommPort = NewCommPort;
}
public string GetCommPort()
{
return CommPort;
}
public void SetBaudRate(Int32 NewBaudRate)
{
Baud = NewBaudRate;
}
public Int32 GetBaudRate()
{
return Baud;
}
#endregion
#region Operation Procedures
public void COMM_Open()
{
try
{
if (LocalPort != null)
{
LocalPort.Close();
PortOpen = false;
}
LocalPort = new SerialPort(CommPort, Baud, Parity.None, 8, StopBits.One);
LocalPort.WriteBufferSize = 5000;
LocalPort.ReadBufferSize = 5000;
LocalPort.Open();
PortOpen = true;
}
catch (Exception e)
{
string ErrMess = "Exception Detected, " + e.Message+"\n";
if (Constructor == true)
ErrMess = ErrMess + "Constructor = true\n";
else
ErrMess = ErrMess + "Constructor = false\n";
if (PortOpen == true)
ErrMess = ErrMess + "Port Open = true";
else
ErrMess = ErrMess + "Port Open = false";
MessageBox.Show(ErrMess, "Simple Serial Comm (Write 1)");
}
}
public void COMM_Close()
{
try
{
if (LocalPort != null)
{
LocalPort.Close();
PortOpen = false;
}
}
catch (Exception e)
{
string ErrMess = "Exception Detected, " + e.Message + "\n";
if (Constructor == true)
ErrMess = ErrMess + "Constructor = true\n";
else
ErrMess = ErrMess + "Constructor = false\n";
if (PortOpen == true)
ErrMess = ErrMess + "Port Open = true";
else
ErrMess = ErrMess + "Port Open = false";
MessageBox.Show(ErrMess, "Simple Serial Comm (Close)");
}
}
public void COMM_Write(string InputString)
{
//Write String Procedure (Overload 1)
try
{
LocalPort.Write(InputString);
}
catch (Exception e)
{
string ErrMess = "Exception Detected, " + e.Message+"\n";
if (Constructor == true)
ErrMess = ErrMess + "Constructor = true\n";
else
ErrMess = ErrMess + "Constructor = false\n";
if (PortOpen == true)
ErrMess = ErrMess + "Port Open = true";
else
ErrMess = ErrMess + "Port Open = false";
MessageBox.Show(ErrMess, "Simple Serial Comm (Write 1)");
}
}
public void COMM_Write(byte[] BinaryData, Int32 StartElement, Int32 NumElementsToSend)
{
//Write Byte Array Procedure (Overload 2)
try
{
LocalPort.Write(BinaryData, StartElement, NumElementsToSend);
}
catch (Exception e)
{
string ErrMess = "Exception Detected, " + e.Message+"\n";
if (Constructor == true)
ErrMess = ErrMess + "Constructor = true\n";
else
ErrMess = ErrMess + "Constructor = false\n";
if (PortOpen == true)
ErrMess = ErrMess + "Port Open = true";
else
ErrMess = ErrMess + "Port Open = false";
MessageBox.Show(ErrMess, "Simple Serial Comm (Write 2)");
}
}
public string COMM_ReadLine(Int32 BufferSize)
{
//needs work, Implment some sort of smart buffering procedure
try
{
return LocalPort.ReadLine();
}
catch (Exception e)
{
string ErrMess = "Exception Detected, " + e.Message+"\n";
if (Constructor == true)
ErrMess = ErrMess + "Constructor = true\n";
else
ErrMess = ErrMess + "Constructor = false\n";
if (PortOpen == true)
ErrMess = ErrMess + "Port Open = true";
else
ErrMess = ErrMess + "Port Open = false";
MessageBox.Show(ErrMess, "Simple Serial Comm (Read Line)");
return "Error";
}
}
public string COMM_ReadToChar(char ReadTo)
{
//bool recover = false;
string Fail1 = "The operation has timed out.";
//string Fail2 = "The I/O operation has been aborted because either a thread exit or an application request.";
try
{
LocalPort.ReadTimeout = 1000;
return LocalPort.ReadTo(ReadTo.ToString());
}
catch (Exception e)
{
if (e.Message == Fail1)
return "";
string ErrMess = "Exception Detected, " + e.Message + "\n";
if (Constructor == true)
ErrMess = ErrMess + "Constructor = true\n";
else
ErrMess = ErrMess + "Constructor = false\n";
if (PortOpen == true)
ErrMess = ErrMess + "Port Open = true";
else
ErrMess = ErrMess + "Port Open = false";
MessageBox.Show(ErrMess, "Simple Serial Comm (Read To Char)");
return "Error";
}
}
public void COMM_FlushInputBuffer()
{
LocalPort.DiscardInBuffer();
}
public void COMM_FlushOutputBuffer()
{
LocalPort.DiscardOutBuffer();
}
#endregion
}
}