This is the latest working repository used in our demo video for the Maxim to display temperature readings on Bluetooth

Dependencies:   USBDevice

Committer:
darienf
Date:
Sun May 02 23:09:04 2021 +0000
Revision:
5:bc128a16232f
Parent:
3:36de8b9e4b1a
This is the program that was last used, that has the working temperature and some comments

Who changed what in which revision?

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