我从网站上获得了以下代码,这种串口读取方式是我唯一的选择,因为DataReceived事件通常不起作用。但是这个代码有问题,如果我关闭应用程序,同时转移应用程序永远挂起,但我不明白为什么?既不冻结也不中止线程工作。实际中止线程会导致程序崩溃。
public class CommPort
{
SerialPort _serialPort;
Thread _readThread;
bool _keepReading;
//begin Singleton pattern
static readonly CommPort instance = new CommPort();
// Explicit static constructor to tell C# compiler
// not to mark type as beforefieldinit
static CommPort()
{
}
CommPort()
{
_serialPort = new SerialPort();
_readThread = null;
_keepReading = false;
}
public static CommPort Instance
{
get
{
return instance;
}
}
//end Singleton pattern
//begin Observer pattern
public delegate void EventHandler(string param);
public EventHandler StatusChanged;
public EventHandler DataReceived;
private void StartReading()
{
if (!_keepReading)
{
_keepReading = true;
_readThread = new Thread(new ThreadStart(ReadPort));
_readThread.Start();
}
}
private void StopReading()
{
if (_keepReading)
{
_keepReading = false;
_serialPort.Close();
//_readThread.Join(); //block until exits
_readThread.Abort();
//_readThread = null;
}
}
private void ReadPort()
{
while (_keepReading)
{
if (_serialPort.IsOpen)
{
byte[] readBuffer = new byte[_serialPort.ReadBufferSize + 1];
try
{
// If there are bytes available on the serial port,
// Read returns up to "count" bytes, but will not block (wait)
// for the remaining bytes. If there are no bytes available
// on the serial port, Read will block until at least one byte
// is available on the port, up until the ReadTimeout milliseconds
// have elapsed, at which time a TimeoutException will be thrown.
int count = _serialPort.Read(readBuffer, 0, _serialPort.ReadBufferSize);
String SerialIn = System.Text.Encoding.ASCII.GetString(readBuffer, 0, count);
DataReceived(SerialIn);
}
catch (TimeoutException)
{
}
}
else
{
TimeSpan waitTime = new TimeSpan(0, 0, 0, 0, 50);
Thread.Sleep(waitTime);
}
}
}
/// <summary> Open the serial port with current settings. </summary>
public void Open()
{
Close();
try
{
_serialPort.PortName = Properties.Settings.Default.COMPort;
_serialPort.BaudRate = Properties.Settings.Default.BPS;
_serialPort.Parity = Properties.Settings.Default.Parity;
_serialPort.DataBits = Properties.Settings.Default.DataBit;
_serialPort.StopBits = Properties.Settings.Default.StopBit;
_serialPort.Handshake = Properties.Settings.Default.HandShake;
// Set the read/write timeouts
_serialPort.ReadTimeout = 50;
_serialPort.WriteTimeout = 50;
_serialPort.Open();
StartReading();
}
catch (IOException)
{
StatusChanged(String.Format("{0} does not exist", Properties.Settings.Default.COMPort));
}
catch (UnauthorizedAccessException)
{
StatusChanged(String.Format("{0} already in use", Properties.Settings.Default.COMPort));
}
catch (Exception ex)
{
StatusChanged(String.Format("{0}", ex.ToString()));
}
// Update the status
if (_serialPort.IsOpen)
{
string p = _serialPort.Parity.ToString().Substring(0, 1); //First char
string h = _serialPort.Handshake.ToString();
if (_serialPort.Handshake == Handshake.None)
h = "no handshake"; // more descriptive than "None"
StatusChanged(String.Format("{0}: {1} bps, {2}{3}{4}, {5}",
_serialPort.PortName, _serialPort.BaudRate,
_serialPort.DataBits, p, (int)_serialPort.StopBits, h));
}
else
{
StatusChanged(String.Format("{0} already in use", Properties.Settings.Default.COMPort));
}
}
/// <summary> Close the serial port. </summary>
public void Close()
{
StopReading();
StatusChanged("connection closed");
}
public bool IsOpen
{
get
{
return _serialPort.IsOpen;
}
}
}
答案 0 :(得分:0)
当您在StopReading()中关闭端口时,它将在_serialPort.Read(...)中导致异常。
不确定哪一个确切但它不是TimeOut。你当前的代码让你逃脱,那就是你的线程和你的应用程序被杀死的时候。
因此,在ReadPort()中的while循环周围添加catch(Exceptiopn ex)
。
答案 1 :(得分:-1)
乍一看有两个问题。
首先,您创建了一个公开事件订阅的单例类。这很危险,因为你应该跟踪任何订阅者。否则他们可能永远不会被释放。这可能就是你的情况。
其次,当你管理“IDisposable”时,你应该注意它。因此,SerialPort应该放在类中的IDisposable实现中。但是,这在单身人士课程中没有任何意义。
单例模式应仅用于集中式被动资源,绝不应用于托管“活动”对象,事件等。
希望这有帮助。