Estoy intentando utilizar la propiedad .BaseStream del .NET2.0 SerialPort para realizar lecturas y escrituras asincrónicas (BeginWrite/EndWrite, BeginRead/EndRead).Cómo utilizar correctamente el puerto serie .NET2.0 .BaseStream para la operación asincrónica
Tengo cierto éxito en esto, pero después de un tiempo, noto (usando Process Explorer) un aumento muy gradual en los Handles que está usando la aplicación, y ocasionalmente un hilo adicional, que también aumenta el conteo de Handle.
La tasa de cambio de contexto también aumenta cada vez que aparece un nuevo hilo.
La aplicación envía constantemente 3 bytes a un dispositivo PLC, y obtiene 800 o más bytes, a cambio, y lo hace a una velocidad de transmisión de 57600.
El cDesconecte Delta inicial (de nuevo, desde el explorador de procesos) es alrededor de 2500, lo que parece muy alto de todos modos. Cada vez que aparece un nuevo hilo, este valor aumenta y la carga de la CPU aumenta en consecuencia.
Espero que alguien haya hecho algo similar, y pueda ayudarme, o incluso decir 'En nombre de Dios, no lo hagas de esa manera'.
En el código siguiente, 'this._stream' se obtiene de SerialPort.BaseStream, y CommsResponse es una clase que uso como el objeto de estado IAsyncresult.
Este código es común a una conexión TCP que hago como alternativa al uso del puerto serie (tengo una clase base CommsChannel, con un canal serial y TCP derivado de ella) y no tiene ninguno de estos problemas, así que Tengo la esperanza razonable de que no haya nada de malo en la clase CommsResponse.
Cualquier comentario recibido con gratitud.
/// <summary>
/// Write byte data to the channel.
/// </summary>
/// <param name="bytes">The byte array to write.</param>
private void Write(byte[] bytes)
{
try
{
// Write the data to the port asynchronously.
this._stream.BeginWrite(bytes, 0, bytes.Length, new AsyncCallback(this.WriteCallback), null);
}
catch (IOException ex)
{
// Do stuff.
}
catch (ObjectDisposedException ex)
{
// Do stuff.
}
}
/// <summary>
/// Asynchronous write callback operation.
/// </summary>
private void WriteCallback(IAsyncResult ar)
{
bool writeSuccess = false;
try
{
this._stream.EndWrite(ar);
writeSuccess = true;
}
catch (IOException ex)
{
// Do stuff.
}
// If the write operation completed sucessfully, start the read process.
if (writeSuccess) { this.Read(); }
}
/// <summary>
/// Read byte data from the channel.
/// </summary>
private void Read()
{
try
{
// Create new comms response state object.
CommsResponse response = new CommsResponse();
// Begin the asynchronous read process to get response.
this._stream.BeginRead(this._readBuffer, 0, this._readBuffer.Length, new AsyncCallback(this.ReadCallback), response);
}
catch (IOException ex)
{
// Do stuff.
}
catch (ObjectDisposedException ex)
{
// Do stuff.
}
}
/// <summary>
/// Asynchronous read callback operation.
/// </summary>
private void ReadCallback(IAsyncResult ar)
{
// Retrieve the comms response object.
CommsResponse response = (CommsResponse)ar.AsyncState;
try
{
// Call EndRead to complete call made by BeginRead.
// At this point, new data will be in this._readbuffer.
int numBytesRead = this._stream.EndRead(ar);
if (numBytesRead > 0)
{
// Create byte array to hold newly received bytes.
byte[] rcvdBytes = new byte[numBytesRead];
// Copy received bytes from read buffer to temp byte array
Buffer.BlockCopy(this._readBuffer, 0, rcvdBytes, 0, numBytesRead);
// Append received bytes to the response data byte list.
response.AppendBytes(rcvdBytes);
// Check received bytes for a correct response.
CheckResult result = response.CheckBytes();
switch (result)
{
case CheckResult.Incomplete: // Correct response not yet received.
if (!this._cancelComm)
{
this._stream.BeginRead(this._readBuffer, 0, this._readBuffer.Length,
new AsyncCallback(this.ReadCallback), response);
}
break;
case CheckResult.Correct: // Raise event if complete response received.
this.OnCommResponseEvent(response);
break;
case CheckResult.Invalid: // Incorrect response
// Do stuff.
break;
default: // Unknown response
// Do stuff.
break;
}
}
else
{
// Do stuff.
}
}
catch (IOException ex)
{
// Do stuff.
}
catch (ObjectDisposedException ex)
{
// Do stuff.
}
}
Gracias por su respuesta. Buena sugerencia sobre la creación de las devoluciones de llamada. Lo he intentado, pero la tasa de cambio de mango/hilo/contexto aún aumenta, aunque parece aumentar a un ritmo más lento, por lo que es una mejora. – Andy