【发布时间】:2010-10-02 12:56:08
【问题描述】:
我正在尝试使用 .NET2.0 SerialPort 的 .BaseStream 属性进行异步读写(BeginWrite/EndWrite、BeginRead/EndRead)。
我在这方面取得了一些成功,但一段时间后,我注意到(使用 Process Explorer)应用正在使用的句柄逐渐增加,并且偶尔会增加一个额外的线程,这也增加了句柄计数。
每次出现新线程时,上下文切换率也会增加。
应用程序不断向 PLC 设备发送 3 个字节,并以 57600 的波特率返回 800 个左右的字节。
最初的 CSwitch Delta(同样来自 Process Explorer)大约是 2500,无论如何这似乎非常高。每出现一个新线程,这个值就会增加,CPU负载也会相应增加。
我希望有人可能做过类似的事情,并且可以帮助我,甚至说'以上帝的名义,不要那样做。'
在下面的代码中,'this._stream' 是从 SerialPort.BaseStream 获得的,而 CommsResponse 是我用作 IAsyncresult 状态对象的类。
此代码对于我作为使用串行端口的替代方法创建的 TCP 连接是通用的,(我有一个 CommsChannel 基类,具有从它派生的串行和 TCP 通道)并且它没有这些问题,所以我我有理由相信 CommsResponse 类没有任何问题。
感谢收到任何 cmets。
/// <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.
}
}
【问题讨论】:
标签: c# asynchronous stream serial-port operation