// UNCLASSIFIED /*------------------------------------------------------------------------- RAYTHEON PROPRIETARY: THIS DOCUMENT CONTAINS DATA OR INFORMATION PROPRIETARY TO RAYTHEON COMPANY AND IS RESTRICTED TO USE ONLY BY PERSONS AUTHORIZED BY RAYTHEON COMPANY IN WRITING TO USE IT. DISCLOSURE TO UNAUTHORIZED PERSONS WOULD LIKELY CAUSE SUBSTANTIAL COMPETITIVE HARM TO RAYTHEON COMPANY'S BUSINESS POSITION. NEITHER SAID DOCUMENT NOR ITS CONTENTS SHALL BE FURNISHED OR DISCLOSED TO OR COPIED OR USED BY PERSONS OUTSIDE RAYTHEON COMPANY WITHOUT THE EXPRESS WRITTEN APPROVAL OF RAYTHEON COMPANY. THIS PROPRIETARY NOTICE IS NOT APPLICABLE IF DELIVERED TO THE U.S. GOVERNMENT. UNPUBLISHED WORK - COPYRIGHT RAYTHEON COMPANY. -------------------------------------------------------------------------*/ using System; using System.Threading; using System.Net.Sockets; using Raytheon.Instruments; using Raytheon.Common; namespace Raytheon.Instruments { /// /// Takes raw data from an ICommDevice and throws it in a buffer /// internal class CommReadWorker : IWorkerInterface { #region PrivateClassMembers private ICommDevice _commNode; private MsgDevice _msgHandler; private bool _threadQuitControl; private AutoResetEvent _quitEvent; private byte[] _dataRead; private readonly uint _timeToRestBetweenReadsInMs; #endregion #region PublicFuctions /// /// Constructor /// /// The communication interface /// The message handler for received data /// The number of bytes for the buffer internal to this class. Each individual read will read upto this buffer size (or until the timeout happens) /// Number of ms to rest after a read call public CommReadWorker(ICommDevice commNode, MsgDevice msghandler, uint bufferSize, uint timeToRestBetweenReadsInMs) { _commNode = commNode; _threadQuitControl = false; _msgHandler = msghandler; _quitEvent = new AutoResetEvent(false); _dataRead = new byte[bufferSize]; _timeToRestBetweenReadsInMs = timeToRestBetweenReadsInMs; } /// /// Finalizer /// ~CommReadWorker() { Dispose(false); } /// /// Dispose of this object. Needed for releasing thread/comm resources /// public void Dispose() { try { Dispose(true); GC.SuppressFinalize(this); } catch (Exception err) { try { ErrorLogger.Instance().Write(err.Message + "\r\n" + err.StackTrace); } catch (Exception) { //Do not rethrow. Exception from error logger that has already been garbage collected } } } /// /// Reads the socket and puts data into a buffer /// public void DoWork() { try { while (_threadQuitControl == false) { try { uint numBytesRead = _commNode.Read(ref _dataRead); // add into buffer if (numBytesRead > 0) { _msgHandler.AddData(_dataRead, numBytesRead); } // not using timeToRestBetweenReadsInMs. Just going to wait 1 ms and get back to the read if (_quitEvent.WaitOne(1)) { ErrorLogger.Instance().Write("CommReadWorker::DoWork() - received signal to quit", ErrorLogger.LogLevel.INFO); _threadQuitControl = true; } } catch (SocketException e) { if (e.SocketErrorCode == SocketError.TimedOut) { //expected } else { ErrorLogger.Instance().Write("CommReadWorker::DoWork() - " + e.Message, ErrorLogger.LogLevel.ERROR); } } catch (Exception e) { ErrorLogger.Instance().Write("CommReadWorker::DoWork() - " + e.Message, ErrorLogger.LogLevel.ERROR); } } ErrorLogger.Instance().Write("CommReadWorker::DoWork() - exiting", ErrorLogger.LogLevel.INFO); } catch (Exception err) { ErrorLogger.Instance().Write(err.Message + "\r\n" + err.StackTrace); } } /// /// Commands the worker to stop /// public void QuitWork() { _quitEvent.Set(); _threadQuitControl = true; } /// /// Dispose of this object /// /// protected virtual void Dispose(bool disposing) { try { if (disposing) { _quitEvent.Dispose(); } } catch (Exception err) { try { ErrorLogger.Instance().Write(err.Message + "\r\n" + err.StackTrace); } catch (Exception) { //Do not rethrow. Exception from error logger that has already been garbage collected } } } #endregion } }