events

  • Thread starter Thread starter Marco Martin
  • Start date Start date
M

Marco Martin

Hi,

I'm writing an application that reads a serial port and 1)updates a list and
sends data to a graph.

When I run the application, nothing happens unless I put a break point
anywhere in my code. then I can see the data and everything gets updated,
until the next time I put a break in the code. Otherwise, I have to put a
break on the thread(200ms) and everything works fine for about 1 minute but
then the program start to lag (normal, its waiting 1/5 of a second at every
data received event). I've been fighting with this for about a week now but
still clue why.

any ideas what might cause this?

regards,

Marco
 
Marco,

There are a number of things that can be going on here. Can you show
some of the code you are using to access the serial port?
 
its kind of large but ok;
this is the class I wrote
//***********************************
using System;

using System.Collections;

using System.Runtime.CompilerServices;

using System.Runtime.InteropServices;

using System.Text;

using System.Threading;





namespace Data_Logger_C

{

public class RS232: IDisposable

{

# region "Variables"

private int c_hCommPort;

private int c_nPort;

private int c_nTimeout;

private int c_nBaudRate;

private enDataParity c_enParity;

private enDataStopBit c_enStopBit;

private int c_nDataBit;

private int c_nBufferSize;

private byte[] c_arrRecieveBuffer;

public Thread c_oEvents;

private bool c_bDisposed;

private enMode c_enMode;

private bool c_bUseXonXoff;

private bool c_bEnableEvents;

private int c_nBufThreshold;

private OVERLAPPED c_OvlE;

private OVERLAPPED c_OvlW;

private OVERLAPPED c_OvlR;



# endregion

# region "Constants"

private const int c_conPURGE_RXABORT = 2;

private const int c_conPURGE_RXCLEAR = 8;

private const int c_conPURGE_TXABORT = 1;

private const int c_conPURGE_TXCLEAR = 4;

private const int c_conGENERIC_READ = int.MinValue;

private const int c_conGENERIC_WRITE = 1073741824;

private const int c_conOPEN_EXISTING = 3;

private const int c_conINVALID_HANDLE_VALUE = -1;

private const int c_conIO_BUFFER_SIZE = 1024;

private const int c_conFILE_FLAG_OVERLAPPED = 1073741824;

private const int c_conERROR_IO_PENDING = 997;

private const int c_conWAIT_OBJECT_0 = 0;

private const int c_conERROR_IO_INCOMPLETE = 996;

private const int c_conWAIT_TIMEOUT = 258;

private const int c_conINFINITE = -1;

public event CommEventHandler commEvent;




# endregion

# region "Enumerations"

public enum enDataParity

{

enParity_None = 0,

enPariti_Odd = 1,

enParity_Even = 2,

enParity_Mark = 3,

}

public enum enDataStopBit

{

enStopBit_1 = 1,

enStopBit_2 = 2,

}

private enum enPurgeBuffers

{

enRXAbort = 2,

enRXClear = 8,

enTxAbort = 1,

enTxClear = 4,

}

private enum enLines

{

enSetRts = 3,

enClearRts = 4,

enSetDtr = 5,

enClearDtr = 6,

enResetDev = 7,

enSetBreak = 8,

enClearBreak = 9

}

[FlagsAttribute()]

public enum enModemStatusBits

{

enClearToSendOn = 16,

enDataSetReadyOn = 32,

enRingIndicatorOn = 64,

enCarrierDetect = 128

}

public enum enMode

{

enNonOverlapped = 0,

enOverlapped = 1,

}

[FlagsAttribute()]

public enum enEventMasks

{

enRxChar = 1,

enRXFlag = 2,

enTxBufferEmpty = 4,

enClearToSend = 8,

enDataSetReady = 16,

enCarrierDetect = 32,

enBreak = 64,

enStatusError = 128,

enRing = 256,

}

# endregion

# region "Structures"

[StructLayoutAttribute(LayoutKind.Sequential, Pack=1, Size=0)]

private struct DCB

{

public int DCBlength;

public int BaudRate;

public int Bits1;

public short wReserved;

public short XonLim;

public short XoffLim;

public byte ByteSize;

public byte Parity;

public byte StopBits;

public char XonChar;

public char XoffChar;

public char ErrorChar;

public char EofChar;

public char EvtChar;

public short wReserved2;

}



[StructLayoutAttribute(LayoutKind.Sequential, Pack=1, Size=0)]

private struct COMMTIMEOUTS

{

public int ReadIntervalTimeout;

public int ReadTotalTimeoutMultiplier;

public int ReadTotalTimeoutConstant;

public int WriteTotalTimeoutMultiplier;

public int WriteTotalTimeoutConstant;

}



[StructLayoutAttribute(LayoutKind.Sequential, Pack=1, Size=0)]

public struct OVERLAPPED

{

public int Internal;

public int InternalHigh;

public int Offset;

public int OffsetHigh;

public int hEvent;

}



[StructLayoutAttribute(LayoutKind.Sequential, Pack=1, Size=0)]

private struct COMSTAT

{

public int fBitFields;

public int cbInQue;

public int cbOutQue;

}

# endregion

# region "Properties"

public virtual string InputStreamString

{

get

{

return new ASCIIEncoding().GetString(InputStream);

}

}

public int RecieveBufferSize

{

get

{

return c_nBufferSize;

}

set

{

c_nBufferSize = value;

}

}

public bool UseXonXoff

{

get

{

return c_bUseXonXoff;

}

set

{

c_bUseXonXoff = value;

}

}

public virtual byte[] InputStream

{

get

{

return c_arrRecieveBuffer;

}

}

public int RxBufferThreshold

{

get

{

return c_nBufThreshold;

}

set

{

c_nBufThreshold = value;

}

}

public enModemStatusBits ModemStatus

{

get

{

enModemStatusBits local0;

int local1 = 0;


if (c_hCommPort == -1)

{

throw new ApplicationException("Please initialize and open port before using
this method");

}


if (!GetCommModemStatus(c_hCommPort, ref local1))

{

throw new ApplicationException("Unable to get modem status");

}

else

{

local0 = (enModemStatusBits)local1;

return local0;

}

}

}


public bool Dtr

{

set

{

if (c_hCommPort != -1)

{

if (value)

{

EscapeCommFunction(c_hCommPort, 5);

}

else

{

EscapeCommFunction(c_hCommPort, 6);

}

}

}

}

public bool Rts

{

set

{

if (c_hCommPort != -1)

{

if (value)

{

EscapeCommFunction(c_hCommPort, 3);

}

else

{

EscapeCommFunction(c_hCommPort, 4);

}

}

}

}

public bool IsOpen

{

get

{

return c_hCommPort == -1 == false;

}

}

public virtual int Timeout

{

get

{

return c_nTimeout;

}

set

{

if (value == 0)

{

c_nTimeout = 500;

}

else

{

c_nTimeout = value;

}

SetTimeout();

}

}

public enDataParity Parity

{

get

{

return c_enParity;

}

set

{

c_enParity = value;

}

}

public int Port

{

get

{

return c_nPort;

}

set

{

c_nPort = value;

}

}

public int BaudRate

{

get

{

return c_nBaudRate;

}

set

{

c_nBaudRate = value;

}

}

public int DataBit

{

get

{

return c_nDataBit;

}

set

{

c_nDataBit = value;

}

}

public enDataStopBit StopBit

{

get

{

return c_enStopBit;

}

set

{

c_enStopBit = value;

}

}

# endregion

#region "API CALLS"

[DllImportAttribute("kernel32.dll")]

private static extern int SetCommState(int hCommDev, ref DCB lpDCB);

[DllImportAttribute("kernel32.dll")]

private static extern int GetCommState(int hCommDev, ref DCB lpDCB);

[DllImportAttribute("kernel32.dll")]

private static extern int BuildCommDCB(string lpDef, ref DCB lpDCB);

[DllImportAttribute("kernel32.dll")]

private static extern int SetupComm(int hFile, int dwInQueue, int
dwOutQueue);

[DllImportAttribute("kernel32.dll")]

private static extern int SetCommTimeouts(int hFile, ref COMMTIMEOUTS
lpCommTimeouts);

[DllImportAttribute("kernel32.dll")]

private static extern int GetCommTimeouts(int hFile, ref COMMTIMEOUTS
lpCommTimeouts);

[DllImportAttribute("kernel32.dll")]

private static extern int ClearCommError(int hFile, int lpErrors, ref
COMSTAT lpComStat);

[DllImportAttribute("kernel32.dll")]

private static extern int PurgeComm(int hFile, int dwFlags);

[DllImportAttribute("kernel32.dll")]

private static extern bool EscapeCommFunction(int hFile, long ifunc);

[DllImportAttribute("kernel32.dll")]

private static extern int WaitCommEvent(int hFile, ref enEventMasks Mask,
ref OVERLAPPED lpOverlap);

[DllImportAttribute("kernel32.dll")]

private static extern int WriteFile(int hFile, byte[] Buffer, int
nNumberOfBytesToWrite, ref int lpNumberOfBytesWritten, ref OVERLAPPED
lpOverlapped);

[DllImportAttribute("kernel32.dll")]

private static extern int ReadFile(int hFile, byte[] Buffer, int
nNumberOfBytesToRead, ref int lpNumberOfBytesRead, ref OVERLAPPED
lpOverlapped);

[DllImportAttribute("kernel32.dll")]

private static extern int CreateFile([MarshalAs(UnmanagedType.LPStr)] string
lpFileName, int dwDesiredAccess, int dwShareMode, int lpSecurityAttributes,
int dwCreationDisposition, int dwFlagsAndAttributes, int hTemplateFile);

[DllImportAttribute("kernel32.dll")]

private static extern int CloseHandle(int hObject);

[DllImportAttribute("kernel32.dll")]

private static extern int FormatMessage(int dwFlags, int lpSource, int
dwMessageId, int dwLanguageId, [MarshalAs(UnmanagedType.LPStr)] string
lpBuffer, int nSize, int Arguments);

[DllImportAttribute("kernel32.dll")]

public static extern bool GetCommModemStatus(int hFile, ref int
lpModemStatus);

[DllImportAttribute("kernel32.dll")]

private static extern bool SetEvent(int hEvent);

[DllImportAttribute("kernel32.dll")]

private static extern int CreateEvent(int lpEventAttributes, int
bManualReset, int bInitialState, [MarshalAs(UnmanagedType.LPStr)] string
lpName);

[DllImportAttribute("kernel32.dll")]

private static extern int GetLastError();

[DllImportAttribute("kernel32.dll")]

private static extern int WaitForSingleObject(int hHandle, int
dwMilliseconds);

[DllImportAttribute("kernel32.dll")]

private static extern int GetOverlappedResult(int hFile, ref OVERLAPPED
lpOverlapped, ref int lpNumberOfBytesTransferred, int bWait);

[DllImportAttribute("kernel32.dll")]

private static extern int SetCommMask(int hFile, int lpEvtMask);

[DllImportAttribute("kernel32", EntryPoint="FormatMessageA",
ExactSpelling=true, CharSet=CharSet.Ansi, SetLastError=true)]

private static extern int FormatMessage(int dwFlags, int lpSource, int
dwMessageId, int dwLanguageId, StringBuilder lpBuffer, int nSize, int
Arguments);


#endregion

# region "Constructor"

public RS232()

{

c_hCommPort = -1;

c_nPort = 1;

c_nTimeout = 70;

c_nBaudRate = 38400;

c_enParity = enDataParity.enParity_None;

c_enStopBit = (enDataStopBit)0;

c_nDataBit = 8;

c_nBufferSize = 512;

c_nBufThreshold = 1;






}

# endregion

# region "Public Methods"

//**************************************************************************
*************

// public void Open()

// Purpose : Initializes and Opens comunication port

// Pre-conditions : None

// Arguments : None

// Returns : None

// Post-conditions : None

//**************************************************************************
*************

public void Open()

{

int iRc = 0;

DCB uDcb = new DCB();



//set the working mode

c_enMode = enMode.enOverlapped;

int intMode;

if(c_enMode == enMode.enOverlapped)

{

intMode = (int)c_conFILE_FLAG_OVERLAPPED;

}

else

{

intMode = (int)0;

}

//init com port

if (c_nPort <= 0)

{

throw new ApplicationException("COM Port not defined,use Port property to
set it before invoking InitPort");

}

//create the com port stream handle

try

{

c_hCommPort = CreateFile("\\\\.\\COM" + c_nPort.ToString(),c_conGENERIC_READ
| c_conGENERIC_WRITE, 0, 0, c_conOPEN_EXISTING, intMode, 0);

if (c_hCommPort == -1)

{

//Raise init problems

throw new clsRS232Exception(String.Concat("Unable to open COM",
c_nPort.ToString()));

}


//Clear all previous Comm Errors

int intErrorCode = 0;

COMSTAT oComstat = new COMSTAT();

iRc = ClearCommError(c_hCommPort, intErrorCode, ref oComstat);

//Clear any IO buffers

iRc = PurgeComm(c_hCommPort, (int)(enPurgeBuffers.enRXClear |
enPurgeBuffers.enTxClear));

//Get current Com Settings

iRc = GetCommState(c_hCommPort,ref uDcb);

//update com settings

string strParity = "NOEM";

strParity = strParity.Substring((int)c_enParity, 1);

//set DBC state

string strDBCState = String.Format("baud={0} parity={1} data={2} stop={3}",
c_nBaudRate, strParity, c_nDataBit,(int)c_enStopBit);

iRc = BuildCommDCB(strDBCState,ref uDcb);

uDcb.Parity = (byte)c_enParity;

//set Xon/Xoff state

if (c_bUseXonXoff)

{

uDcb.Bits1 = 768;

}

else

{

uDcb.Bits1 = 0;

}

iRc = SetCommState(c_hCommPort, ref uDcb);

if (iRc == 0)

{

string strErrorText = Err2Text(GetLastError());

throw new clsRS232Exception(String.Concat("Unable to set COM state ",
strErrorText));

}

//setup TxRx buffers

iRc = SetupComm(c_hCommPort, c_nBufferSize, c_nBufferSize);

//now set the timeouts

SetTimeout();

//If we need events, enable them

if (c_bEnableEvents)

{

this.EnableEvents();

}


}

catch (Exception e)

{

throw new clsRS232Exception(e.Message, e);

}

}

//**************************************************************************
*************

// public void Open(int Port, int BaudRate, int DataBit, enDataParity
Parity, enDataStopBit StopBit, int BufferSize)

// Purpose : Initializes comunication port and calls Open()

// Pre-conditions : None

// Arguments : None

// Returns : None

// Post-conditions : None

//**************************************************************************
*************

public void Open(int Port, int BaudRate, int DataBit, enDataParity Parity,
enDataStopBit StopBit, int BufferSize)

{

this.Port = Port;

this.BaudRate = BaudRate;

this.DataBit = DataBit;

this.Parity = Parity;

this.StopBit = StopBit;

this.RecieveBufferSize = BufferSize;

Open();

}

//**************************************************************************
*************

// public void Close()

// Purpose : closes communications port

// Pre-conditions : None

// Arguments : None

// Returns : None

// Post-conditions : None

//**************************************************************************
*************

public void Close()

{

if (c_hCommPort != -1)

{

if (c_bEnableEvents == true)

{

this.DisableEvents();

c_bEnableEvents = true;

}

CloseHandle(c_hCommPort);

c_hCommPort = -1;

}

}

public void Write(byte[] Buffer)

{

c_OvlW = new OVERLAPPED();

int intBytesWritten = 0;

int iRc = 0;

if (c_hCommPort == -1)

{

throw new ApplicationException("Please initialize and open port before using
this method");

}

try

{

// creates the event

c_OvlW.hEvent = CreateEvent(0, 1, 0, null);

if (c_OvlW.hEvent == 0)

{

throw new ApplicationException("Error creating event for overlapped
writing");

}

//clears the IO buffers and sends the data

PurgeComm(c_hCommPort, c_conPURGE_TXCLEAR);


int intTemp = 0;

iRc = WriteFile(c_hCommPort, Buffer, Buffer.Length,ref intTemp,ref c_OvlW);

if(iRc == 0)

{


if(GetLastError() != c_conERROR_IO_PENDING)

{

throw new ApplicationException("Write command error");

}

else

{

//check tX results

if(GetOverlappedResult((int)c_hCommPort, ref c_OvlW, ref intBytesWritten, 1)
== 0)

{

throw new ApplicationException("Write pending error");

}

else

{

//are all bytes sent?

if(intBytesWritten != Buffer.Length)

{

throw new ApplicationException("Write Error - Bytes Written: " +
intBytesWritten.ToString() + " of " + Buffer.Length.ToString());

}

}

}

}

}

finally

{

CloseHandle(c_OvlW.hEvent);

}

}

public void Write(string Buffer)

{

// ASCIIEncoding aSCIIEncoding = new ASCIIEncoding();

// byte[] bs = Encoding.GetEncoding(1252).GetBytes(Buffer);

// Write(bs);

//ASCIIEncoding oEncoder = new ASCIIEncoding();

Encoding oEnc = ASCIIEncoding.GetEncoding(1252);

byte[] arrBytesToWrite = oEnc.GetBytes(Buffer);

this.Write(arrBytesToWrite);

}

public int Read(int Bytes2Read)

{

int iRc = 0;

int intReadChars = 0;

//bool bolReading;

if (Bytes2Read == 0)

{

Bytes2Read = c_nBufferSize;

}

c_OvlR = new OVERLAPPED();

if (c_hCommPort == -1)

{

throw new ApplicationException("Please initialize and open port before using
this method");


}

try

{

//get bytes from port

c_OvlR.hEvent = CreateEvent(0, 1, 0, null);

if (c_OvlR.hEvent == 0)

{

throw new ApplicationException("Error creating event for overlapped
reading");

}

//clear io buffer and read the data

PurgeComm(c_hCommPort, c_conPURGE_RXCLEAR);

c_arrRecieveBuffer = new byte[Bytes2Read - 1];


iRc = ReadFile(c_hCommPort, c_arrRecieveBuffer, Bytes2Read, ref
intReadChars, ref c_OvlR);


if (iRc == 0)

{

if(GetLastError() != c_conERROR_IO_PENDING)

{

throw new ApplicationException("Read Pending Error");

}

else

{

//Wait for chars

iRc = WaitForSingleObject(c_OvlR.hEvent, c_nTimeout);

switch(iRc)

{

case c_conWAIT_OBJECT_0:

{

//We have some data received

if(GetOverlappedResult(c_hCommPort,ref c_OvlR, ref intReadChars, 0) == 0)

{

throw new ApplicationException("Read Pending Error.");

}

else

{

return intReadChars;

}

}

case c_conWAIT_TIMEOUT:

{

throw new clsRS232Exception("Read Timeout");

}

default:

{

throw new ApplicationException("General Read Error");

}

}

}

}

else

{

return intReadChars;

}

}

finally

{

CloseHandle(c_OvlR.hEvent);

}


}

public void ClearInputBuffer()

{

if (c_hCommPort != -1)

{

PurgeComm(c_hCommPort, c_conPURGE_RXCLEAR);

}

}

public bool CheckLineStatus(enModemStatusBits Line)

{

return Convert.ToBoolean(ModemStatus & Line);

}

public void EnableEvents()

{

if (c_hCommPort == -1)

{

throw new ApplicationException("Please initialize and open port before using
this method");

}

if (c_oEvents == null)

{

c_bEnableEvents = true;

c_oEvents = new Thread(new ThreadStart(this.EventsWatcher));

//c_oEvents.Priority = ThreadPriority.Highest;

c_oEvents.Start();

}

}

public void DisableEvents()

{

if (c_bEnableEvents == true)

{

RS232 rs232 = this;

Monitor.Enter(rs232);

try

{

c_bEnableEvents = false;

}

finally

{

Monitor.Exit(rs232);

}

if (c_OvlE.hEvent != 0)

{

SetEvent(c_OvlE.hEvent);

}

c_oEvents = null;

}

}

public virtual void Dispose()

{

if (this.c_bDisposed || this.c_hCommPort == -1)

{

try

{

this.Close();

}

finally

{

this.c_bDisposed = true;

GC.SuppressFinalize(this);

}

}

}

# endregion

# region "Private Methods"

private void SetTimeout()

{

COMMTIMEOUTS uCTM;

if (c_hCommPort != -1)

{

uCTM.ReadIntervalTimeout = 0;

uCTM.ReadTotalTimeoutMultiplier = 0;

uCTM.ReadTotalTimeoutConstant = c_nTimeout;

uCTM.WriteTotalTimeoutMultiplier = 10;

uCTM.WriteTotalTimeoutConstant = 100;

SetCommTimeouts(c_hCommPort, ref uCTM);

}

}

private string Err2Text(int lCode)

{

string str;

StringBuilder stringBuilder = new StringBuilder(256);

if (FormatMessage(4096, 0, lCode, 0, stringBuilder, 256, 0) > 0)

{

str = stringBuilder.ToString();

}

else

{

str = "Error not found.";

}

return str;

}

//**************************************************************************
*************

// private void EventsWatcher()

// Purpose : Watches for all events raising events when they arrive to the
port

// Pre-conditions : None

// Arguments :

// Returns :

// Post-conditions : None

//**************************************************************************
*************

private void EventsWatcher()

{


//events to watch

enEventMasks lMask = enEventMasks.enRxChar | enEventMasks.enRXFlag |
enEventMasks.enClearToSend | enEventMasks.enDataSetReady |
enEventMasks.enCarrierDetect | enEventMasks.enBreak |
enEventMasks.enStatusError | enEventMasks.enRing;

int intBytesRead = 0;

int intTotBytes = 0;

int intErrMask = 0;


ArrayList arrBuf = new ArrayList();

COMSTAT uComStat = new COMSTAT();

c_OvlE = new OVERLAPPED();



//create the event

c_OvlE.hEvent = CreateEvent(0 , 1, 0, null);

if (c_OvlE.hEvent == 0)

{

throw new ApplicationException("Error creating event for overlapped
reading");

}

//set the mask

RS232.SetCommMask(c_hCommPort, (int)lMask);

//Look for the RxChar

while(c_bEnableEvents==true)

{

WaitCommEvent(c_hCommPort,ref lMask, ref c_OvlE);


switch(WaitForSingleObject(c_OvlE.hEvent, c_conINFINITE))

{

case c_conWAIT_OBJECT_0:

{

//Abort detected

if(c_bEnableEvents == false)

{

//break out of while loop

break;

}

if((lMask & enEventMasks.enRxChar) > 0)

{

//read incomming data

ClearCommError(c_hCommPort, intErrMask, ref uComStat);

if(intErrMask == 0)

{

//we've got to resize the array

if(uComStat.cbInQue > 0)

{

c_arrRecieveBuffer = null;

c_arrRecieveBuffer = new byte[uComStat.cbInQue - 1];

}

if(ReadFile(c_hCommPort, c_arrRecieveBuffer, uComStat.cbInQue, ref
intBytesRead, ref c_OvlE) > 0)

{

if(intBytesRead > 0)

{

//Bytes have been read, put in temporary buffer

if(intTotBytes < c_nBufThreshold)

{

arrBuf.AddRange(c_arrRecieveBuffer);

intTotBytes += intBytesRead;

}

//if the threshhold is reached, raise the event

if(intTotBytes >= c_nBufThreshold)

{

//copy the temp buffer into array

//we've got to resize the array

c_arrRecieveBuffer = new byte[intTotBytes - 1];

arrBuf.CopyTo(c_arrRecieveBuffer);

//now raise the event

try

{

RS232_CommEvent(this, lMask);

}

finally

{

intTotBytes = 0;

arrBuf.Clear();

}

}

}

}

}

}

else

{

//just raise the event

RS232_CommEvent(this, lMask);

}

break;

}//end case

default:

{

throw new ApplicationException(Err2Text(GetLastError()));

}


}//end switch

}//end while


//release hold on event

CloseHandle(c_OvlE.hEvent);

c_OvlE.hEvent = 0;

}//end eventswatcher

private void RS232_CommEvent(RS232 source, enEventMasks Mask)

{

commEvent(source, Mask);

}

# endregion

# region "Destructor"

~RS232()

{

try

{

if (!c_bDisposed)

{

if (c_bEnableEvents)

{

DisableEvents();

}

Close();

}

}

finally

{

this.Dispose();

}

}

# endregion





}

}






Any help is appreciated thanks

Marco


Nicholas Paldino said:
Marco,

There are a number of things that can be going on here. Can you show
some of the code you are using to access the serial port?


--
- Nicholas Paldino [.NET/C# MVP]
- (e-mail address removed)

Marco Martin said:
Hi,

I'm writing an application that reads a serial port and 1)updates a list and
sends data to a graph.

When I run the application, nothing happens unless I put a break point
anywhere in my code. then I can see the data and everything gets updated,
until the next time I put a break in the code. Otherwise, I have to put a
break on the thread(200ms) and everything works fine for about 1 minute but
then the program start to lag (normal, its waiting 1/5 of a second at every
data received event). I've been fighting with this for about a week now but
still clue why.

any ideas what might cause this?

regards,

Marco
 
Marco,

Can you trim it down to the sections that are relevant? Which calls
read from the port, etc, etc? The code is a bit much to look through.

--
- Nicholas Paldino [.NET/C# MVP]
- (e-mail address removed)

Marco Martin said:
its kind of large but ok;
this is the class I wrote
//***********************************
using System;

using System.Collections;

using System.Runtime.CompilerServices;

using System.Runtime.InteropServices;

using System.Text;

using System.Threading;





namespace Data_Logger_C

{

public class RS232: IDisposable

{

# region "Variables"

private int c_hCommPort;

private int c_nPort;

private int c_nTimeout;

private int c_nBaudRate;

private enDataParity c_enParity;

private enDataStopBit c_enStopBit;

private int c_nDataBit;

private int c_nBufferSize;

private byte[] c_arrRecieveBuffer;

public Thread c_oEvents;

private bool c_bDisposed;

private enMode c_enMode;

private bool c_bUseXonXoff;

private bool c_bEnableEvents;

private int c_nBufThreshold;

private OVERLAPPED c_OvlE;

private OVERLAPPED c_OvlW;

private OVERLAPPED c_OvlR;



# endregion

# region "Constants"

private const int c_conPURGE_RXABORT = 2;

private const int c_conPURGE_RXCLEAR = 8;

private const int c_conPURGE_TXABORT = 1;

private const int c_conPURGE_TXCLEAR = 4;

private const int c_conGENERIC_READ = int.MinValue;

private const int c_conGENERIC_WRITE = 1073741824;

private const int c_conOPEN_EXISTING = 3;

private const int c_conINVALID_HANDLE_VALUE = -1;

private const int c_conIO_BUFFER_SIZE = 1024;

private const int c_conFILE_FLAG_OVERLAPPED = 1073741824;

private const int c_conERROR_IO_PENDING = 997;

private const int c_conWAIT_OBJECT_0 = 0;

private const int c_conERROR_IO_INCOMPLETE = 996;

private const int c_conWAIT_TIMEOUT = 258;

private const int c_conINFINITE = -1;

public event CommEventHandler commEvent;




# endregion

# region "Enumerations"

public enum enDataParity

{

enParity_None = 0,

enPariti_Odd = 1,

enParity_Even = 2,

enParity_Mark = 3,

}

public enum enDataStopBit

{

enStopBit_1 = 1,

enStopBit_2 = 2,

}

private enum enPurgeBuffers

{

enRXAbort = 2,

enRXClear = 8,

enTxAbort = 1,

enTxClear = 4,

}

private enum enLines

{

enSetRts = 3,

enClearRts = 4,

enSetDtr = 5,

enClearDtr = 6,

enResetDev = 7,

enSetBreak = 8,

enClearBreak = 9

}

[FlagsAttribute()]

public enum enModemStatusBits

{

enClearToSendOn = 16,

enDataSetReadyOn = 32,

enRingIndicatorOn = 64,

enCarrierDetect = 128

}

public enum enMode

{

enNonOverlapped = 0,

enOverlapped = 1,

}

[FlagsAttribute()]

public enum enEventMasks

{

enRxChar = 1,

enRXFlag = 2,

enTxBufferEmpty = 4,

enClearToSend = 8,

enDataSetReady = 16,

enCarrierDetect = 32,

enBreak = 64,

enStatusError = 128,

enRing = 256,

}

# endregion

# region "Structures"

[StructLayoutAttribute(LayoutKind.Sequential, Pack=1, Size=0)]

private struct DCB

{

public int DCBlength;

public int BaudRate;

public int Bits1;

public short wReserved;

public short XonLim;

public short XoffLim;

public byte ByteSize;

public byte Parity;

public byte StopBits;

public char XonChar;

public char XoffChar;

public char ErrorChar;

public char EofChar;

public char EvtChar;

public short wReserved2;

}



[StructLayoutAttribute(LayoutKind.Sequential, Pack=1, Size=0)]

private struct COMMTIMEOUTS

{

public int ReadIntervalTimeout;

public int ReadTotalTimeoutMultiplier;

public int ReadTotalTimeoutConstant;

public int WriteTotalTimeoutMultiplier;

public int WriteTotalTimeoutConstant;

}



[StructLayoutAttribute(LayoutKind.Sequential, Pack=1, Size=0)]

public struct OVERLAPPED

{

public int Internal;

public int InternalHigh;

public int Offset;

public int OffsetHigh;

public int hEvent;

}



[StructLayoutAttribute(LayoutKind.Sequential, Pack=1, Size=0)]

private struct COMSTAT

{

public int fBitFields;

public int cbInQue;

public int cbOutQue;

}

# endregion

# region "Properties"

public virtual string InputStreamString

{

get

{

return new ASCIIEncoding().GetString(InputStream);

}

}

public int RecieveBufferSize

{

get

{

return c_nBufferSize;

}

set

{

c_nBufferSize = value;

}

}

public bool UseXonXoff

{

get

{

return c_bUseXonXoff;

}

set

{

c_bUseXonXoff = value;

}

}

public virtual byte[] InputStream

{

get

{

return c_arrRecieveBuffer;

}

}

public int RxBufferThreshold

{

get

{

return c_nBufThreshold;

}

set

{

c_nBufThreshold = value;

}

}

public enModemStatusBits ModemStatus

{

get

{

enModemStatusBits local0;

int local1 = 0;


if (c_hCommPort == -1)

{

throw new ApplicationException("Please initialize and open port before using
this method");

}


if (!GetCommModemStatus(c_hCommPort, ref local1))

{

throw new ApplicationException("Unable to get modem status");

}

else

{

local0 = (enModemStatusBits)local1;

return local0;

}

}

}


public bool Dtr

{

set

{

if (c_hCommPort != -1)

{

if (value)

{

EscapeCommFunction(c_hCommPort, 5);

}

else

{

EscapeCommFunction(c_hCommPort, 6);

}

}

}

}

public bool Rts

{

set

{

if (c_hCommPort != -1)

{

if (value)

{

EscapeCommFunction(c_hCommPort, 3);

}

else

{

EscapeCommFunction(c_hCommPort, 4);

}

}

}

}

public bool IsOpen

{

get

{

return c_hCommPort == -1 == false;

}

}

public virtual int Timeout

{

get

{

return c_nTimeout;

}

set

{

if (value == 0)

{

c_nTimeout = 500;

}

else

{

c_nTimeout = value;

}

SetTimeout();

}

}

public enDataParity Parity

{

get

{

return c_enParity;

}

set

{

c_enParity = value;

}

}

public int Port

{

get

{

return c_nPort;

}

set

{

c_nPort = value;

}

}

public int BaudRate

{

get

{

return c_nBaudRate;

}

set

{

c_nBaudRate = value;

}

}

public int DataBit

{

get

{

return c_nDataBit;

}

set

{

c_nDataBit = value;

}

}

public enDataStopBit StopBit

{

get

{

return c_enStopBit;

}

set

{

c_enStopBit = value;

}

}

# endregion

#region "API CALLS"

[DllImportAttribute("kernel32.dll")]

private static extern int SetCommState(int hCommDev, ref DCB lpDCB);

[DllImportAttribute("kernel32.dll")]

private static extern int GetCommState(int hCommDev, ref DCB lpDCB);

[DllImportAttribute("kernel32.dll")]

private static extern int BuildCommDCB(string lpDef, ref DCB lpDCB);

[DllImportAttribute("kernel32.dll")]

private static extern int SetupComm(int hFile, int dwInQueue, int
dwOutQueue);

[DllImportAttribute("kernel32.dll")]

private static extern int SetCommTimeouts(int hFile, ref COMMTIMEOUTS
lpCommTimeouts);

[DllImportAttribute("kernel32.dll")]

private static extern int GetCommTimeouts(int hFile, ref COMMTIMEOUTS
lpCommTimeouts);

[DllImportAttribute("kernel32.dll")]

private static extern int ClearCommError(int hFile, int lpErrors, ref
COMSTAT lpComStat);

[DllImportAttribute("kernel32.dll")]

private static extern int PurgeComm(int hFile, int dwFlags);

[DllImportAttribute("kernel32.dll")]

private static extern bool EscapeCommFunction(int hFile, long ifunc);

[DllImportAttribute("kernel32.dll")]

private static extern int WaitCommEvent(int hFile, ref enEventMasks Mask,
ref OVERLAPPED lpOverlap);

[DllImportAttribute("kernel32.dll")]

private static extern int WriteFile(int hFile, byte[] Buffer, int
nNumberOfBytesToWrite, ref int lpNumberOfBytesWritten, ref OVERLAPPED
lpOverlapped);

[DllImportAttribute("kernel32.dll")]

private static extern int ReadFile(int hFile, byte[] Buffer, int
nNumberOfBytesToRead, ref int lpNumberOfBytesRead, ref OVERLAPPED
lpOverlapped);

[DllImportAttribute("kernel32.dll")]

private static extern int CreateFile([MarshalAs(UnmanagedType.LPStr)] string
lpFileName, int dwDesiredAccess, int dwShareMode, int lpSecurityAttributes,
int dwCreationDisposition, int dwFlagsAndAttributes, int hTemplateFile);

[DllImportAttribute("kernel32.dll")]

private static extern int CloseHandle(int hObject);

[DllImportAttribute("kernel32.dll")]

private static extern int FormatMessage(int dwFlags, int lpSource, int
dwMessageId, int dwLanguageId, [MarshalAs(UnmanagedType.LPStr)] string
lpBuffer, int nSize, int Arguments);

[DllImportAttribute("kernel32.dll")]

public static extern bool GetCommModemStatus(int hFile, ref int
lpModemStatus);

[DllImportAttribute("kernel32.dll")]

private static extern bool SetEvent(int hEvent);

[DllImportAttribute("kernel32.dll")]

private static extern int CreateEvent(int lpEventAttributes, int
bManualReset, int bInitialState, [MarshalAs(UnmanagedType.LPStr)] string
lpName);

[DllImportAttribute("kernel32.dll")]

private static extern int GetLastError();

[DllImportAttribute("kernel32.dll")]

private static extern int WaitForSingleObject(int hHandle, int
dwMilliseconds);

[DllImportAttribute("kernel32.dll")]

private static extern int GetOverlappedResult(int hFile, ref OVERLAPPED
lpOverlapped, ref int lpNumberOfBytesTransferred, int bWait);

[DllImportAttribute("kernel32.dll")]

private static extern int SetCommMask(int hFile, int lpEvtMask);

[DllImportAttribute("kernel32", EntryPoint="FormatMessageA",
ExactSpelling=true, CharSet=CharSet.Ansi, SetLastError=true)]

private static extern int FormatMessage(int dwFlags, int lpSource, int
dwMessageId, int dwLanguageId, StringBuilder lpBuffer, int nSize, int
Arguments);


#endregion

# region "Constructor"

public RS232()

{

c_hCommPort = -1;

c_nPort = 1;

c_nTimeout = 70;

c_nBaudRate = 38400;

c_enParity = enDataParity.enParity_None;

c_enStopBit = (enDataStopBit)0;

c_nDataBit = 8;

c_nBufferSize = 512;

c_nBufThreshold = 1;






}

# endregion

# region "Public Methods"

//**************************************************************************
*************

// public void Open()

// Purpose : Initializes and Opens comunication port

// Pre-conditions : None

// Arguments : None

// Returns : None

// Post-conditions : None

//**************************************************************************
*************

public void Open()

{

int iRc = 0;

DCB uDcb = new DCB();



//set the working mode

c_enMode = enMode.enOverlapped;

int intMode;

if(c_enMode == enMode.enOverlapped)

{

intMode = (int)c_conFILE_FLAG_OVERLAPPED;

}

else

{

intMode = (int)0;

}

//init com port

if (c_nPort <= 0)

{

throw new ApplicationException("COM Port not defined,use Port property to
set it before invoking InitPort");

}

//create the com port stream handle

try

{

c_hCommPort = CreateFile("\\\\.\\COM" + c_nPort.ToString(),c_conGENERIC_READ
| c_conGENERIC_WRITE, 0, 0, c_conOPEN_EXISTING, intMode, 0);

if (c_hCommPort == -1)

{

//Raise init problems

throw new clsRS232Exception(String.Concat("Unable to open COM",
c_nPort.ToString()));

}


//Clear all previous Comm Errors

int intErrorCode = 0;

COMSTAT oComstat = new COMSTAT();

iRc = ClearCommError(c_hCommPort, intErrorCode, ref oComstat);

//Clear any IO buffers

iRc = PurgeComm(c_hCommPort, (int)(enPurgeBuffers.enRXClear |
enPurgeBuffers.enTxClear));

//Get current Com Settings

iRc = GetCommState(c_hCommPort,ref uDcb);

//update com settings

string strParity = "NOEM";

strParity = strParity.Substring((int)c_enParity, 1);

//set DBC state

string strDBCState = String.Format("baud={0} parity={1} data={2} stop={3}",
c_nBaudRate, strParity, c_nDataBit,(int)c_enStopBit);

iRc = BuildCommDCB(strDBCState,ref uDcb);

uDcb.Parity = (byte)c_enParity;

//set Xon/Xoff state

if (c_bUseXonXoff)

{

uDcb.Bits1 = 768;

}

else

{

uDcb.Bits1 = 0;

}

iRc = SetCommState(c_hCommPort, ref uDcb);

if (iRc == 0)

{

string strErrorText = Err2Text(GetLastError());

throw new clsRS232Exception(String.Concat("Unable to set COM state ",
strErrorText));

}

//setup TxRx buffers

iRc = SetupComm(c_hCommPort, c_nBufferSize, c_nBufferSize);

//now set the timeouts

SetTimeout();

//If we need events, enable them

if (c_bEnableEvents)

{

this.EnableEvents();

}


}

catch (Exception e)

{

throw new clsRS232Exception(e.Message, e);

}

}

//**************************************************************************
*************

// public void Open(int Port, int BaudRate, int DataBit, enDataParity
Parity, enDataStopBit StopBit, int BufferSize)

// Purpose : Initializes comunication port and calls Open()

// Pre-conditions : None

// Arguments : None

// Returns : None

// Post-conditions : None

//**************************************************************************
*************

public void Open(int Port, int BaudRate, int DataBit, enDataParity Parity,
enDataStopBit StopBit, int BufferSize)

{

this.Port = Port;

this.BaudRate = BaudRate;

this.DataBit = DataBit;

this.Parity = Parity;

this.StopBit = StopBit;

this.RecieveBufferSize = BufferSize;

Open();

}

//**************************************************************************
*************

// public void Close()

// Purpose : closes communications port

// Pre-conditions : None

// Arguments : None

// Returns : None

// Post-conditions : None

//**************************************************************************
*************

public void Close()

{

if (c_hCommPort != -1)

{

if (c_bEnableEvents == true)

{

this.DisableEvents();

c_bEnableEvents = true;

}

CloseHandle(c_hCommPort);

c_hCommPort = -1;

}

}

public void Write(byte[] Buffer)

{

c_OvlW = new OVERLAPPED();

int intBytesWritten = 0;

int iRc = 0;

if (c_hCommPort == -1)

{

throw new ApplicationException("Please initialize and open port before using
this method");

}

try

{

// creates the event

c_OvlW.hEvent = CreateEvent(0, 1, 0, null);

if (c_OvlW.hEvent == 0)

{

throw new ApplicationException("Error creating event for overlapped
writing");

}

//clears the IO buffers and sends the data

PurgeComm(c_hCommPort, c_conPURGE_TXCLEAR);


int intTemp = 0;

iRc = WriteFile(c_hCommPort, Buffer, Buffer.Length,ref intTemp,ref c_OvlW);

if(iRc == 0)

{


if(GetLastError() != c_conERROR_IO_PENDING)

{

throw new ApplicationException("Write command error");

}

else

{

//check tX results

if(GetOverlappedResult((int)c_hCommPort, ref c_OvlW, ref intBytesWritten, 1)
== 0)

{

throw new ApplicationException("Write pending error");

}

else

{

//are all bytes sent?

if(intBytesWritten != Buffer.Length)

{

throw new ApplicationException("Write Error - Bytes Written: " +
intBytesWritten.ToString() + " of " + Buffer.Length.ToString());

}

}

}

}

}

finally

{

CloseHandle(c_OvlW.hEvent);

}

}

public void Write(string Buffer)

{

// ASCIIEncoding aSCIIEncoding = new ASCIIEncoding();

// byte[] bs = Encoding.GetEncoding(1252).GetBytes(Buffer);

// Write(bs);

//ASCIIEncoding oEncoder = new ASCIIEncoding();

Encoding oEnc = ASCIIEncoding.GetEncoding(1252);

byte[] arrBytesToWrite = oEnc.GetBytes(Buffer);

this.Write(arrBytesToWrite);

}

public int Read(int Bytes2Read)

{

int iRc = 0;

int intReadChars = 0;

//bool bolReading;

if (Bytes2Read == 0)

{

Bytes2Read = c_nBufferSize;

}

c_OvlR = new OVERLAPPED();

if (c_hCommPort == -1)

{

throw new ApplicationException("Please initialize and open port before using
this method");


}

try

{

//get bytes from port

c_OvlR.hEvent = CreateEvent(0, 1, 0, null);

if (c_OvlR.hEvent == 0)

{

throw new ApplicationException("Error creating event for overlapped
reading");

}

//clear io buffer and read the data

PurgeComm(c_hCommPort, c_conPURGE_RXCLEAR);

c_arrRecieveBuffer = new byte[Bytes2Read - 1];


iRc = ReadFile(c_hCommPort, c_arrRecieveBuffer, Bytes2Read, ref
intReadChars, ref c_OvlR);


if (iRc == 0)

{

if(GetLastError() != c_conERROR_IO_PENDING)

{

throw new ApplicationException("Read Pending Error");

}

else

{

//Wait for chars

iRc = WaitForSingleObject(c_OvlR.hEvent, c_nTimeout);

switch(iRc)

{

case c_conWAIT_OBJECT_0:

{

//We have some data received

if(GetOverlappedResult(c_hCommPort,ref c_OvlR, ref intReadChars, 0) == 0)

{

throw new ApplicationException("Read Pending Error.");

}

else

{

return intReadChars;

}

}

case c_conWAIT_TIMEOUT:

{

throw new clsRS232Exception("Read Timeout");

}

default:

{

throw new ApplicationException("General Read Error");

}

}

}

}

else

{

return intReadChars;

}

}

finally

{

CloseHandle(c_OvlR.hEvent);

}


}

public void ClearInputBuffer()

{

if (c_hCommPort != -1)

{

PurgeComm(c_hCommPort, c_conPURGE_RXCLEAR);

}

}

public bool CheckLineStatus(enModemStatusBits Line)

{

return Convert.ToBoolean(ModemStatus & Line);

}

public void EnableEvents()

{

if (c_hCommPort == -1)

{

throw new ApplicationException("Please initialize and open port before using
this method");

}

if (c_oEvents == null)

{

c_bEnableEvents = true;

c_oEvents = new Thread(new ThreadStart(this.EventsWatcher));

//c_oEvents.Priority = ThreadPriority.Highest;

c_oEvents.Start();

}

}

public void DisableEvents()

{

if (c_bEnableEvents == true)

{

RS232 rs232 = this;

Monitor.Enter(rs232);

try

{

c_bEnableEvents = false;

}

finally

{

Monitor.Exit(rs232);

}

if (c_OvlE.hEvent != 0)

{

SetEvent(c_OvlE.hEvent);

}

c_oEvents = null;

}

}

public virtual void Dispose()

{

if (this.c_bDisposed || this.c_hCommPort == -1)

{

try

{

this.Close();

}

finally

{

this.c_bDisposed = true;

GC.SuppressFinalize(this);

}

}

}

# endregion

# region "Private Methods"

private void SetTimeout()

{

COMMTIMEOUTS uCTM;

if (c_hCommPort != -1)

{

uCTM.ReadIntervalTimeout = 0;

uCTM.ReadTotalTimeoutMultiplier = 0;

uCTM.ReadTotalTimeoutConstant = c_nTimeout;

uCTM.WriteTotalTimeoutMultiplier = 10;

uCTM.WriteTotalTimeoutConstant = 100;

SetCommTimeouts(c_hCommPort, ref uCTM);

}

}

private string Err2Text(int lCode)

{

string str;

StringBuilder stringBuilder = new StringBuilder(256);

if (FormatMessage(4096, 0, lCode, 0, stringBuilder, 256, 0) > 0)

{

str = stringBuilder.ToString();

}

else

{

str = "Error not found.";

}

return str;

}

//**************************************************************************
*************

// private void EventsWatcher()

// Purpose : Watches for all events raising events when they arrive to the
port

// Pre-conditions : None

// Arguments :

// Returns :

// Post-conditions : None

//**************************************************************************
*************

private void EventsWatcher()

{


//events to watch

enEventMasks lMask = enEventMasks.enRxChar | enEventMasks.enRXFlag |
enEventMasks.enClearToSend | enEventMasks.enDataSetReady |
enEventMasks.enCarrierDetect | enEventMasks.enBreak |
enEventMasks.enStatusError | enEventMasks.enRing;

int intBytesRead = 0;

int intTotBytes = 0;

int intErrMask = 0;


ArrayList arrBuf = new ArrayList();

COMSTAT uComStat = new COMSTAT();

c_OvlE = new OVERLAPPED();



//create the event

c_OvlE.hEvent = CreateEvent(0 , 1, 0, null);

if (c_OvlE.hEvent == 0)

{

throw new ApplicationException("Error creating event for overlapped
reading");

}

//set the mask

RS232.SetCommMask(c_hCommPort, (int)lMask);

//Look for the RxChar

while(c_bEnableEvents==true)

{

WaitCommEvent(c_hCommPort,ref lMask, ref c_OvlE);


switch(WaitForSingleObject(c_OvlE.hEvent, c_conINFINITE))

{

case c_conWAIT_OBJECT_0:

{

//Abort detected

if(c_bEnableEvents == false)

{

//break out of while loop

break;

}

if((lMask & enEventMasks.enRxChar) > 0)

{

//read incomming data

ClearCommError(c_hCommPort, intErrMask, ref uComStat);

if(intErrMask == 0)

{

//we've got to resize the array

if(uComStat.cbInQue > 0)

{

c_arrRecieveBuffer = null;

c_arrRecieveBuffer = new byte[uComStat.cbInQue - 1];

}

if(ReadFile(c_hCommPort, c_arrRecieveBuffer, uComStat.cbInQue, ref
intBytesRead, ref c_OvlE) > 0)

{

if(intBytesRead > 0)

{

//Bytes have been read, put in temporary buffer

if(intTotBytes < c_nBufThreshold)

{

arrBuf.AddRange(c_arrRecieveBuffer);

intTotBytes += intBytesRead;

}

//if the threshhold is reached, raise the event

if(intTotBytes >= c_nBufThreshold)

{

//copy the temp buffer into array

//we've got to resize the array

c_arrRecieveBuffer = new byte[intTotBytes - 1];

arrBuf.CopyTo(c_arrRecieveBuffer);

//now raise the event

try

{

RS232_CommEvent(this, lMask);

}

finally

{

intTotBytes = 0;

arrBuf.Clear();

}

}

}

}

}

}

else

{

//just raise the event

RS232_CommEvent(this, lMask);

}

break;

}//end case

default:

{

throw new ApplicationException(Err2Text(GetLastError()));

}


}//end switch

}//end while


//release hold on event

CloseHandle(c_OvlE.hEvent);

c_OvlE.hEvent = 0;

}//end eventswatcher

private void RS232_CommEvent(RS232 source, enEventMasks Mask)

{

commEvent(source, Mask);

}

# endregion

# region "Destructor"

~RS232()

{

try

{

if (!c_bDisposed)

{

if (c_bEnableEvents)

{

DisableEvents();

}

Close();

}

}

finally

{

this.Dispose();

}

}

# endregion





}

}






Any help is appreciated thanks

Marco


message news:[email protected]...
Marco,

There are a number of things that can be going on here. Can you show
some of the code you are using to access the serial port?


--
- Nicholas Paldino [.NET/C# MVP]
- (e-mail address removed)

Marco Martin said:
Hi,

I'm writing an application that reads a serial port and 1)updates a
list
and
sends data to a graph.

When I run the application, nothing happens unless I put a break point
anywhere in my code. then I can see the data and everything gets updated,
until the next time I put a break in the code. Otherwise, I have to
put
a minute
but now
but
 
Back
Top