public void Start() { Debug.Assert(Form1.GUIthreadHashcode == Thread.CurrentThread.GetHashCode()); // should ONLY be called from GUI thread Debug.Assert(!timer.Enabled); // successive Start or Stop calls are BAD Debug.WriteLine("SerialOperationTimer " + name + ": Start"); if (runningTimer != null) { Debug.Assert(false); // Lets have a look in the debugger NOW throw new System.Exception("SerialOperationTimer " + name + ": Attempted 'Start' while " + runningTimer.name + " is still running"); } // Start background processing // Release GUI thread's lock on the serial port, so background thread can grab it Monitor.Exit(XXX_Conn.SerialPortLockObject); runningTimer = this; timer.Enabled = true; }
public void Stop() { Debug.Assert(Form1.GUIthreadHashcode == Thread.CurrentThread.GetHashCode()); // should ONLY be called from GUI thread Debug.Assert(timer.Enabled); // successive Start or Stop calls are BAD Debug.WriteLine("SerialOperationTimer " + name + ": Stop"); if (runningTimer != this) { Debug.Assert(false); // Lets have a look in the debugger NOW throw new System.Exception("SerialOperationTimer " + name + ": Attempted 'Stop' while not running"); } // Stop further background processing from being initiated, timer.Enabled = false; // but, background processing may still be in progress from the last timer tick... runningTimer = null; // Purge serial input and output buffers. Clearing input buf causes any blocking read in progress in background thread to throw // System.IO.IOException "The I/O operation has been aborted because of either a thread exit or an application request.\r\n" if (Form1.xxConnection.PortIsOpen) { Form1.xxConnection.CiCommDiscardBothBuffers(); } bool lockTaken = false; // Now, GUI thread needs the lock back. // 3 sec REALLY should be enough time for background thread to cleanup and release the lock: Monitor.TryEnter(XXX_Conn.SerialPortLockObject, 3000, ref lockTaken); if (!lockTaken) { throw new Exception("Serial port lock not yet released by background timer thread " + name); } if (Form1.xxConnection.PortIsOpen) { // Its possible there's still stuff in transit from device (for example, background thread just completed // sending an ACQ command as it was stopped). So, sync up with the device... int r = Form1.xxConnection.CiSync(); Debug.Assert(r == XXX_Conn.CI_OK); if (r != XXX_Conn.CI_OK) { throw new Exception("Cannot re-sync with device after disabling timer thread " + name); } } }