repo time

Dependencies:   mbed MAX14720 MAX30205 USBDevice

Committer:
darienf
Date:
Tue Apr 06 06:41:40 2021 +0000
Revision:
20:6d2af70c92ab
another repo

Who changed what in which revision?

UserRevisionLine numberNew contents of line
darienf 20:6d2af70c92ab 1 using System;
darienf 20:6d2af70c92ab 2 using System.Collections.Generic;
darienf 20:6d2af70c92ab 3 using System.Linq;
darienf 20:6d2af70c92ab 4 using System.Text;
darienf 20:6d2af70c92ab 5 using System.Threading.Tasks;
darienf 20:6d2af70c92ab 6 using System.Threading;
darienf 20:6d2af70c92ab 7 using System.Reflection;
darienf 20:6d2af70c92ab 8 using System.IO;
darienf 20:6d2af70c92ab 9
darienf 20:6d2af70c92ab 10 using System.IO.Ports;
darienf 20:6d2af70c92ab 11 using SerialPortTester;
darienf 20:6d2af70c92ab 12
darienf 20:6d2af70c92ab 13 using Common.Logging;
darienf 20:6d2af70c92ab 14
darienf 20:6d2af70c92ab 15 namespace SerialWrap
darienf 20:6d2af70c92ab 16 {
darienf 20:6d2af70c92ab 17 public interface ISerialPortIo : IDisposable
darienf 20:6d2af70c92ab 18 {
darienf 20:6d2af70c92ab 19 string PortName { get; }
darienf 20:6d2af70c92ab 20 string ReadLine();
darienf 20:6d2af70c92ab 21 void WriteLine(string text);
darienf 20:6d2af70c92ab 22 }
darienf 20:6d2af70c92ab 23
darienf 20:6d2af70c92ab 24 public class SerialPortConfig
darienf 20:6d2af70c92ab 25 {
darienf 20:6d2af70c92ab 26 public string Name { get; private set; }
darienf 20:6d2af70c92ab 27 public int BaudRate { get; private set; }
darienf 20:6d2af70c92ab 28 public int DataBits { get; private set; }
darienf 20:6d2af70c92ab 29 public StopBits StopBits { get; private set; }
darienf 20:6d2af70c92ab 30 public Parity Parity { get; private set; }
darienf 20:6d2af70c92ab 31 public bool DtrEnable { get; private set; }
darienf 20:6d2af70c92ab 32 public bool RtsEnable { get; private set; }
darienf 20:6d2af70c92ab 33
darienf 20:6d2af70c92ab 34 public SerialPortConfig(
darienf 20:6d2af70c92ab 35 string name,
darienf 20:6d2af70c92ab 36 int baudRate,
darienf 20:6d2af70c92ab 37 int dataBits,
darienf 20:6d2af70c92ab 38 StopBits stopBits,
darienf 20:6d2af70c92ab 39 Parity parity,
darienf 20:6d2af70c92ab 40 bool dtrEnable,
darienf 20:6d2af70c92ab 41 bool rtsEnable)
darienf 20:6d2af70c92ab 42 {
darienf 20:6d2af70c92ab 43 if (String.IsNullOrWhiteSpace(name)) throw new ArgumentNullException("name");
darienf 20:6d2af70c92ab 44
darienf 20:6d2af70c92ab 45 this.RtsEnable = rtsEnable;
darienf 20:6d2af70c92ab 46 this.BaudRate = baudRate;
darienf 20:6d2af70c92ab 47 this.DataBits = dataBits;
darienf 20:6d2af70c92ab 48 this.StopBits = stopBits;
darienf 20:6d2af70c92ab 49 this.Parity = parity;
darienf 20:6d2af70c92ab 50 this.DtrEnable = dtrEnable;
darienf 20:6d2af70c92ab 51 this.Name = name;
darienf 20:6d2af70c92ab 52 }
darienf 20:6d2af70c92ab 53
darienf 20:6d2af70c92ab 54 public override string ToString()
darienf 20:6d2af70c92ab 55 {
darienf 20:6d2af70c92ab 56 return String.Format(
darienf 20:6d2af70c92ab 57 "{0} (Baud: {1}/DataBits: {2}/Parity: {3}/StopBits: {4}/{5})",
darienf 20:6d2af70c92ab 58 this.Name,
darienf 20:6d2af70c92ab 59 this.BaudRate,
darienf 20:6d2af70c92ab 60 this.DataBits,
darienf 20:6d2af70c92ab 61 this.Parity,
darienf 20:6d2af70c92ab 62 this.StopBits,
darienf 20:6d2af70c92ab 63 this.RtsEnable ? "RTS" : "No RTS");
darienf 20:6d2af70c92ab 64 }
darienf 20:6d2af70c92ab 65 }
darienf 20:6d2af70c92ab 66
darienf 20:6d2af70c92ab 67 // Wrapper around SerialPort
darienf 20:6d2af70c92ab 68 public class SerialPortIo : ISerialPortIo
darienf 20:6d2af70c92ab 69 {
darienf 20:6d2af70c92ab 70 protected ILog Log { get; private set; }
darienf 20:6d2af70c92ab 71 static readonly ILog s_Log = LogManager.GetLogger(typeof(SerialPortIo));
darienf 20:6d2af70c92ab 72
darienf 20:6d2af70c92ab 73 readonly SerialPort _port;
darienf 20:6d2af70c92ab 74 readonly Stream _internalSerialStream;
darienf 20:6d2af70c92ab 75
darienf 20:6d2af70c92ab 76 private int readTimeout;
darienf 20:6d2af70c92ab 77 private int writeTimeout;
darienf 20:6d2af70c92ab 78
darienf 20:6d2af70c92ab 79 public int ReadTimeout
darienf 20:6d2af70c92ab 80 {
darienf 20:6d2af70c92ab 81 get { return readTimeout; }
darienf 20:6d2af70c92ab 82 set
darienf 20:6d2af70c92ab 83 {
darienf 20:6d2af70c92ab 84 readTimeout = value;
darienf 20:6d2af70c92ab 85 _port.ReadTimeout = readTimeout;
darienf 20:6d2af70c92ab 86 }
darienf 20:6d2af70c92ab 87 }
darienf 20:6d2af70c92ab 88
darienf 20:6d2af70c92ab 89 public int WriteTimeout
darienf 20:6d2af70c92ab 90 {
darienf 20:6d2af70c92ab 91 get { return writeTimeout; }
darienf 20:6d2af70c92ab 92 set
darienf 20:6d2af70c92ab 93 {
darienf 20:6d2af70c92ab 94 writeTimeout = value;
darienf 20:6d2af70c92ab 95 _port.WriteTimeout = writeTimeout;
darienf 20:6d2af70c92ab 96 }
darienf 20:6d2af70c92ab 97 }
darienf 20:6d2af70c92ab 98
darienf 20:6d2af70c92ab 99 public void DiscardInBuffer()
darienf 20:6d2af70c92ab 100 {
darienf 20:6d2af70c92ab 101 _port.DiscardInBuffer();
darienf 20:6d2af70c92ab 102 }
darienf 20:6d2af70c92ab 103
darienf 20:6d2af70c92ab 104 public bool IsOpen
darienf 20:6d2af70c92ab 105 {
darienf 20:6d2af70c92ab 106 get { return _port.IsOpen; }
darienf 20:6d2af70c92ab 107 }
darienf 20:6d2af70c92ab 108
darienf 20:6d2af70c92ab 109 public SerialPortIo(SerialPortConfig portConfig)
darienf 20:6d2af70c92ab 110 {
darienf 20:6d2af70c92ab 111 if (portConfig == null) throw new ArgumentNullException("portConfig");
darienf 20:6d2af70c92ab 112
darienf 20:6d2af70c92ab 113 this.Log = LogManager.GetLogger(this.GetType());
darienf 20:6d2af70c92ab 114
darienf 20:6d2af70c92ab 115 // http://zachsaw.blogspot.com/2010/07/net-serialport-woes.html
darienf 20:6d2af70c92ab 116 SerialPortFixer.Execute(portConfig.Name);
darienf 20:6d2af70c92ab 117
darienf 20:6d2af70c92ab 118 var port = new SerialPort(
darienf 20:6d2af70c92ab 119 portConfig.Name,
darienf 20:6d2af70c92ab 120 portConfig.BaudRate,
darienf 20:6d2af70c92ab 121 portConfig.Parity,
darienf 20:6d2af70c92ab 122 portConfig.DataBits,
darienf 20:6d2af70c92ab 123 portConfig.StopBits)
darienf 20:6d2af70c92ab 124 {
darienf 20:6d2af70c92ab 125 RtsEnable = portConfig.RtsEnable,
darienf 20:6d2af70c92ab 126 DtrEnable = portConfig.DtrEnable,
darienf 20:6d2af70c92ab 127 ReadTimeout = 5000,
darienf 20:6d2af70c92ab 128 WriteTimeout = 5000
darienf 20:6d2af70c92ab 129 };
darienf 20:6d2af70c92ab 130 port.Open();
darienf 20:6d2af70c92ab 131
darienf 20:6d2af70c92ab 132 try
darienf 20:6d2af70c92ab 133 {
darienf 20:6d2af70c92ab 134 this._internalSerialStream = port.BaseStream;
darienf 20:6d2af70c92ab 135 this._port = port;
darienf 20:6d2af70c92ab 136 this._port.DiscardInBuffer();
darienf 20:6d2af70c92ab 137 this._port.DiscardOutBuffer();
darienf 20:6d2af70c92ab 138 }
darienf 20:6d2af70c92ab 139 catch (Exception ex)
darienf 20:6d2af70c92ab 140 {
darienf 20:6d2af70c92ab 141 Stream internalStream = this._internalSerialStream;
darienf 20:6d2af70c92ab 142
darienf 20:6d2af70c92ab 143 if (internalStream == null)
darienf 20:6d2af70c92ab 144 {
darienf 20:6d2af70c92ab 145 FieldInfo field = typeof(SerialPort).GetField(
darienf 20:6d2af70c92ab 146 "internalSerialStream",
darienf 20:6d2af70c92ab 147 BindingFlags.Instance | BindingFlags.NonPublic);
darienf 20:6d2af70c92ab 148
darienf 20:6d2af70c92ab 149 // This will happen if the SerialPort class is changed
darienf 20:6d2af70c92ab 150 // in future versions of the .NET Framework
darienf 20:6d2af70c92ab 151 if (field == null)
darienf 20:6d2af70c92ab 152 {
darienf 20:6d2af70c92ab 153 this.Log.WarnFormat(
darienf 20:6d2af70c92ab 154 "An exception occured while creating the serial port adaptor, "
darienf 20:6d2af70c92ab 155 + "the internal stream reference was not acquired and we were unable "
darienf 20:6d2af70c92ab 156 + "to get it using reflection. The serial port may not be accessible "
darienf 20:6d2af70c92ab 157 + "any further until the serial port object finalizer has been run: {0}",
darienf 20:6d2af70c92ab 158 ex);
darienf 20:6d2af70c92ab 159
darienf 20:6d2af70c92ab 160 throw;
darienf 20:6d2af70c92ab 161 }
darienf 20:6d2af70c92ab 162
darienf 20:6d2af70c92ab 163 internalStream = (Stream)field.GetValue(port);
darienf 20:6d2af70c92ab 164 }
darienf 20:6d2af70c92ab 165
darienf 20:6d2af70c92ab 166 this.Log.DebugFormat(
darienf 20:6d2af70c92ab 167 "An error occurred while constructing the serial port adaptor: {0}", ex);
darienf 20:6d2af70c92ab 168
darienf 20:6d2af70c92ab 169 SafeDisconnect(port, internalStream);
darienf 20:6d2af70c92ab 170 throw;
darienf 20:6d2af70c92ab 171 }
darienf 20:6d2af70c92ab 172 }
darienf 20:6d2af70c92ab 173
darienf 20:6d2af70c92ab 174 public string PortName
darienf 20:6d2af70c92ab 175 {
darienf 20:6d2af70c92ab 176 get { return this._port.PortName; }
darienf 20:6d2af70c92ab 177 }
darienf 20:6d2af70c92ab 178
darienf 20:6d2af70c92ab 179 public int Read(char[] buffer, int offset, int count)
darienf 20:6d2af70c92ab 180 {
darienf 20:6d2af70c92ab 181 return this._port.Read(buffer, offset, count);
darienf 20:6d2af70c92ab 182 }
darienf 20:6d2af70c92ab 183
darienf 20:6d2af70c92ab 184 public int Read(byte[] buffer, int offset, int count)
darienf 20:6d2af70c92ab 185 {
darienf 20:6d2af70c92ab 186 return this._port.Read(buffer, offset, count);
darienf 20:6d2af70c92ab 187 }
darienf 20:6d2af70c92ab 188
darienf 20:6d2af70c92ab 189 public string ReadLine()
darienf 20:6d2af70c92ab 190 {
darienf 20:6d2af70c92ab 191 //return this._port.ReadTo(Environment.NewLine);
darienf 20:6d2af70c92ab 192 return this._port.ReadLine();
darienf 20:6d2af70c92ab 193 }
darienf 20:6d2af70c92ab 194
darienf 20:6d2af70c92ab 195 public string ReadExisting()
darienf 20:6d2af70c92ab 196 {
darienf 20:6d2af70c92ab 197 return this._port.ReadExisting();
darienf 20:6d2af70c92ab 198 }
darienf 20:6d2af70c92ab 199
darienf 20:6d2af70c92ab 200 public void Write(string text)
darienf 20:6d2af70c92ab 201 {
darienf 20:6d2af70c92ab 202 this._port.Write(text);
darienf 20:6d2af70c92ab 203 }
darienf 20:6d2af70c92ab 204
darienf 20:6d2af70c92ab 205 public void Write(char[] buffer, int offset, int count)
darienf 20:6d2af70c92ab 206 {
darienf 20:6d2af70c92ab 207 this._port.Write(buffer, offset, count);
darienf 20:6d2af70c92ab 208 }
darienf 20:6d2af70c92ab 209
darienf 20:6d2af70c92ab 210
darienf 20:6d2af70c92ab 211 public void WriteLine(string text)
darienf 20:6d2af70c92ab 212 {
darienf 20:6d2af70c92ab 213 //this._port.Write(text);
darienf 20:6d2af70c92ab 214 //this._port.Write("\r");
darienf 20:6d2af70c92ab 215 this._port.WriteLine(text);
darienf 20:6d2af70c92ab 216 }
darienf 20:6d2af70c92ab 217
darienf 20:6d2af70c92ab 218 public void Dispose()
darienf 20:6d2af70c92ab 219 {
darienf 20:6d2af70c92ab 220 this.Dispose(true);
darienf 20:6d2af70c92ab 221 }
darienf 20:6d2af70c92ab 222
darienf 20:6d2af70c92ab 223 protected void Dispose(bool disposing)
darienf 20:6d2af70c92ab 224 {
darienf 20:6d2af70c92ab 225 SafeDisconnect(this._port, this._internalSerialStream);
darienf 20:6d2af70c92ab 226
darienf 20:6d2af70c92ab 227 if (disposing)
darienf 20:6d2af70c92ab 228 {
darienf 20:6d2af70c92ab 229 GC.SuppressFinalize(this);
darienf 20:6d2af70c92ab 230 }
darienf 20:6d2af70c92ab 231 }
darienf 20:6d2af70c92ab 232
darienf 20:6d2af70c92ab 233 /// <summary>
darienf 20:6d2af70c92ab 234 /// Safely closes a serial port and its internal stream even if
darienf 20:6d2af70c92ab 235 /// a USB serial interface was physically removed from the system
darienf 20:6d2af70c92ab 236 /// in a reliable manner.
darienf 20:6d2af70c92ab 237 /// </summary>
darienf 20:6d2af70c92ab 238 /// <param name="port"></param>
darienf 20:6d2af70c92ab 239 /// <param name="internalSerialStream"></param>
darienf 20:6d2af70c92ab 240 /// <remarks>
darienf 20:6d2af70c92ab 241 /// The <see cref="SerialPort"/> class has 3 different problems in disposal
darienf 20:6d2af70c92ab 242 /// in case of a USB serial device that is physically removed:
darienf 20:6d2af70c92ab 243 ///
darienf 20:6d2af70c92ab 244 /// 1. The eventLoopRunner is asked to stop and <see cref="SerialPort.IsOpen"/>
darienf 20:6d2af70c92ab 245 /// returns false. Upon disposal this property is checked and closing
darienf 20:6d2af70c92ab 246 /// the internal serial stream is skipped, thus keeping the original
darienf 20:6d2af70c92ab 247 /// handle open indefinitely (until the finalizer runs which leads to the next problem)
darienf 20:6d2af70c92ab 248 ///
darienf 20:6d2af70c92ab 249 /// The solution for this one is to manually close the internal serial stream.
darienf 20:6d2af70c92ab 250 /// We can get its reference by <see cref="SerialPort.BaseStream" />
darienf 20:6d2af70c92ab 251 /// before the exception has happened or by reflection and getting the
darienf 20:6d2af70c92ab 252 /// "internalSerialStream" field.
darienf 20:6d2af70c92ab 253 ///
darienf 20:6d2af70c92ab 254 /// 2. Closing the internal serial stream throws an exception and closes
darienf 20:6d2af70c92ab 255 /// the internal handle without waiting for its eventLoopRunner thread to finish,
darienf 20:6d2af70c92ab 256 /// causing an uncatchable ObjectDisposedException from it later on when the finalizer
darienf 20:6d2af70c92ab 257 /// runs (which oddly avoids throwing the exception but still fails to wait for
darienf 20:6d2af70c92ab 258 /// the eventLoopRunner).
darienf 20:6d2af70c92ab 259 ///
darienf 20:6d2af70c92ab 260 /// The solution is to manually ask the event loop runner thread to shutdown
darienf 20:6d2af70c92ab 261 /// (via reflection) and waiting for it before closing the internal serial stream.
darienf 20:6d2af70c92ab 262 ///
darienf 20:6d2af70c92ab 263 /// 3. Since Dispose throws exceptions, the finalizer is not suppressed.
darienf 20:6d2af70c92ab 264 ///
darienf 20:6d2af70c92ab 265 /// The solution is to suppress their finalizers at the beginning.
darienf 20:6d2af70c92ab 266 /// </remarks>
darienf 20:6d2af70c92ab 267 static void SafeDisconnect(SerialPort port, Stream internalSerialStream)
darienf 20:6d2af70c92ab 268 {
darienf 20:6d2af70c92ab 269 GC.SuppressFinalize(port);
darienf 20:6d2af70c92ab 270 GC.SuppressFinalize(internalSerialStream);
darienf 20:6d2af70c92ab 271
darienf 20:6d2af70c92ab 272 ShutdownEventLoopHandler(internalSerialStream);
darienf 20:6d2af70c92ab 273
darienf 20:6d2af70c92ab 274 try
darienf 20:6d2af70c92ab 275 {
darienf 20:6d2af70c92ab 276 s_Log.DebugFormat("Disposing internal serial stream");
darienf 20:6d2af70c92ab 277 internalSerialStream.Close();
darienf 20:6d2af70c92ab 278 }
darienf 20:6d2af70c92ab 279 catch (Exception ex)
darienf 20:6d2af70c92ab 280 {
darienf 20:6d2af70c92ab 281 s_Log.DebugFormat(
darienf 20:6d2af70c92ab 282 "Exception in serial stream shutdown of port {0}: {1}", port.PortName, ex);
darienf 20:6d2af70c92ab 283 }
darienf 20:6d2af70c92ab 284
darienf 20:6d2af70c92ab 285 try
darienf 20:6d2af70c92ab 286 {
darienf 20:6d2af70c92ab 287 s_Log.DebugFormat("Disposing serial port");
darienf 20:6d2af70c92ab 288 port.Close();
darienf 20:6d2af70c92ab 289 }
darienf 20:6d2af70c92ab 290 catch (Exception ex)
darienf 20:6d2af70c92ab 291 {
darienf 20:6d2af70c92ab 292 s_Log.DebugFormat("Exception in port {0} shutdown: {1}", port.PortName, ex);
darienf 20:6d2af70c92ab 293 }
darienf 20:6d2af70c92ab 294 }
darienf 20:6d2af70c92ab 295
darienf 20:6d2af70c92ab 296 static void ShutdownEventLoopHandler(Stream internalSerialStream)
darienf 20:6d2af70c92ab 297 {
darienf 20:6d2af70c92ab 298 try
darienf 20:6d2af70c92ab 299 {
darienf 20:6d2af70c92ab 300 s_Log.DebugFormat("Working around .NET SerialPort class Dispose bug");
darienf 20:6d2af70c92ab 301
darienf 20:6d2af70c92ab 302 FieldInfo eventRunnerField = internalSerialStream.GetType()
darienf 20:6d2af70c92ab 303 .GetField("eventRunner", BindingFlags.NonPublic | BindingFlags.Instance);
darienf 20:6d2af70c92ab 304
darienf 20:6d2af70c92ab 305 if (eventRunnerField == null)
darienf 20:6d2af70c92ab 306 {
darienf 20:6d2af70c92ab 307 s_Log.WarnFormat(
darienf 20:6d2af70c92ab 308 "Unable to find EventLoopRunner field. "
darienf 20:6d2af70c92ab 309 + "SerialPort workaround failure. Application may crash after "
darienf 20:6d2af70c92ab 310 + "disposing SerialPort unless .NET 1.1 unhandled exception "
darienf 20:6d2af70c92ab 311 + "policy is enabled from the application's config file.");
darienf 20:6d2af70c92ab 312 }
darienf 20:6d2af70c92ab 313 else
darienf 20:6d2af70c92ab 314 {
darienf 20:6d2af70c92ab 315 object eventRunner = eventRunnerField.GetValue(internalSerialStream);
darienf 20:6d2af70c92ab 316 Type eventRunnerType = eventRunner.GetType();
darienf 20:6d2af70c92ab 317
darienf 20:6d2af70c92ab 318 FieldInfo endEventLoopFieldInfo = eventRunnerType.GetField(
darienf 20:6d2af70c92ab 319 "endEventLoop", BindingFlags.Instance | BindingFlags.NonPublic);
darienf 20:6d2af70c92ab 320
darienf 20:6d2af70c92ab 321 FieldInfo eventLoopEndedSignalFieldInfo = eventRunnerType.GetField(
darienf 20:6d2af70c92ab 322 "eventLoopEndedSignal", BindingFlags.Instance | BindingFlags.NonPublic);
darienf 20:6d2af70c92ab 323
darienf 20:6d2af70c92ab 324 FieldInfo waitCommEventWaitHandleFieldInfo = eventRunnerType.GetField(
darienf 20:6d2af70c92ab 325 "waitCommEventWaitHandle", BindingFlags.Instance | BindingFlags.NonPublic);
darienf 20:6d2af70c92ab 326
darienf 20:6d2af70c92ab 327 if (endEventLoopFieldInfo == null
darienf 20:6d2af70c92ab 328 || eventLoopEndedSignalFieldInfo == null
darienf 20:6d2af70c92ab 329 || waitCommEventWaitHandleFieldInfo == null)
darienf 20:6d2af70c92ab 330 {
darienf 20:6d2af70c92ab 331 s_Log.WarnFormat(
darienf 20:6d2af70c92ab 332 "Unable to find the EventLoopRunner internal wait handle or loop signal fields. "
darienf 20:6d2af70c92ab 333 + "SerialPort workaround failure. Application may crash after "
darienf 20:6d2af70c92ab 334 + "disposing SerialPort unless .NET 1.1 unhandled exception "
darienf 20:6d2af70c92ab 335 + "policy is enabled from the application's config file.");
darienf 20:6d2af70c92ab 336 }
darienf 20:6d2af70c92ab 337 else
darienf 20:6d2af70c92ab 338 {
darienf 20:6d2af70c92ab 339 s_Log.DebugFormat(
darienf 20:6d2af70c92ab 340 "Waiting for the SerialPort internal EventLoopRunner thread to finish...");
darienf 20:6d2af70c92ab 341
darienf 20:6d2af70c92ab 342 var eventLoopEndedWaitHandle =
darienf 20:6d2af70c92ab 343 (WaitHandle)eventLoopEndedSignalFieldInfo.GetValue(eventRunner);
darienf 20:6d2af70c92ab 344 var waitCommEventWaitHandle =
darienf 20:6d2af70c92ab 345 (ManualResetEvent)waitCommEventWaitHandleFieldInfo.GetValue(eventRunner);
darienf 20:6d2af70c92ab 346
darienf 20:6d2af70c92ab 347 endEventLoopFieldInfo.SetValue(eventRunner, true);
darienf 20:6d2af70c92ab 348
darienf 20:6d2af70c92ab 349 // Sometimes the event loop handler resets the wait handle
darienf 20:6d2af70c92ab 350 // before exiting the loop and hangs (in case of USB disconnect)
darienf 20:6d2af70c92ab 351 // In case it takes too long, brute-force it out of its wait by
darienf 20:6d2af70c92ab 352 // setting the handle again.
darienf 20:6d2af70c92ab 353 do
darienf 20:6d2af70c92ab 354 {
darienf 20:6d2af70c92ab 355 waitCommEventWaitHandle.Set();
darienf 20:6d2af70c92ab 356 } while (!eventLoopEndedWaitHandle.WaitOne(2000));
darienf 20:6d2af70c92ab 357
darienf 20:6d2af70c92ab 358 s_Log.DebugFormat("Wait completed. Now it is safe to continue disposal.");
darienf 20:6d2af70c92ab 359 }
darienf 20:6d2af70c92ab 360 }
darienf 20:6d2af70c92ab 361 }
darienf 20:6d2af70c92ab 362 catch (Exception ex)
darienf 20:6d2af70c92ab 363 {
darienf 20:6d2af70c92ab 364 s_Log.ErrorFormat(
darienf 20:6d2af70c92ab 365 "SerialPort workaround failure. Application may crash after "
darienf 20:6d2af70c92ab 366 + "disposing SerialPort unless .NET 1.1 unhandled exception "
darienf 20:6d2af70c92ab 367 + "policy is enabled from the application's config file: {0}",
darienf 20:6d2af70c92ab 368 ex);
darienf 20:6d2af70c92ab 369 }
darienf 20:6d2af70c92ab 370 }
darienf 20:6d2af70c92ab 371 }
darienf 20:6d2af70c92ab 372 }