我正在尝试使用.NET2.0 SerialPort的.BaseStream属性进行异步读写(BeginWrite / EndWrite,BeginRead / EndRead)。
我在这方面有一些成功经验,但是一段时间后,我注意到(使用Process Explorer),应用程序使用的句柄会逐渐增加,并偶尔会出现额外的线程,这也会增加句柄计数。
每次出现新线程时,上下文切换率也会增加。
该应用程序不断向PLC设备发送3个字节,并返回大约800个字节,并以波特率57600进行操作。
最初的CSwitch Delta(同样来自Process Explorer)约为2500,无论如何都似乎很高。每次出现新线程时,此值都会增加,并相应地增加CPU负载。
我希望有人可能已经做过类似的事情,并且可以帮助我,或者甚至说“天哪,不要那样做”。
在下面的代码中,“this._stream”是从SerialPort.BaseStream获取的,并且CommsResponse是我用作IAsyncresult状态对象的类。
我使用TCP连接作为替代使用串行端口的常见代码(我有一个CommsChannel基类,派生自它的是串行和TCP通道),并且它没有这些问题,因此我有理由相信CommsResponse类没有任何问题。
任何意见都将不胜感激。
我在这方面有一些成功经验,但是一段时间后,我注意到(使用Process Explorer),应用程序使用的句柄会逐渐增加,并偶尔会出现额外的线程,这也会增加句柄计数。
每次出现新线程时,上下文切换率也会增加。
该应用程序不断向PLC设备发送3个字节,并返回大约800个字节,并以波特率57600进行操作。
最初的CSwitch Delta(同样来自Process Explorer)约为2500,无论如何都似乎很高。每次出现新线程时,此值都会增加,并相应地增加CPU负载。
我希望有人可能已经做过类似的事情,并且可以帮助我,或者甚至说“天哪,不要那样做”。
在下面的代码中,“this._stream”是从SerialPort.BaseStream获取的,并且CommsResponse是我用作IAsyncresult状态对象的类。
我使用TCP连接作为替代使用串行端口的常见代码(我有一个CommsChannel基类,派生自它的是串行和TCP通道),并且它没有这些问题,因此我有理由相信CommsResponse类没有任何问题。
任何意见都将不胜感激。
/// <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.
}
}