/// <summary> /// Notify the observers /// </summary> /// <param name="message"></param> public override void HandleMessage(IMessageIOIO message) { // messages must support notification to do notification... IMessageNotificationIOIO notifier = message as IMessageNotificationIOIO; if (notifier != null) { foreach (IObserverIOIO observer in Interested_) { try { notifier.Notify(observer); } catch (Exception e) { LOG.Error("Caught exception ", e); } } } }
/// <summary> /// This method notifies the observers in parallel and does not wait. /// </summary> /// <param name="message"></param> public override void HandleMessage(IMessageIOIO message) { // messages must support notification to do notification... IMessageNotificationIOIO notifier = message as IMessageNotificationIOIO; if (notifier != null) { foreach (IObserverIOIO observer in Interested_) { try { // copy the loop value so it doesn't get replaced IObserverIOIO taskObserver = observer; Task.Factory.StartNew(() => notifier.Notify(taskObserver)); } catch (Exception e) { LOG.Error("Caught exception ", e); } } } }
////////////////////////////////////////////////////////// //// Outbound Thread Handling section //// This belongs in IOProtocolOutgoing -- similar to IOProtocolIngoing organization ////////////////////////////////////////////////////////// /// <summary> /// We only one thread pulling items off the queue /// </summary> public virtual void run() { try { // pick something fast for humans but long for a computer TimeSpan timeout = new TimeSpan(0, 0, 0, 0, 100); while (true) { this.CancelTokenSource_.Token.ThrowIfCancellationRequested(); IPostMessageCommand nextMessage; // use timeout so we can get cancellation token // use blocking queue so that we aren't spinning bool didTake = WorkQueue.TryTake(out nextMessage, timeout); if (didTake && nextMessage != null) { LOG.Debug("T:" + OutgoingTask_.Id + " Execution candidate: " + nextMessage); // notify observers we are ABOUT to send a message // the observers can block the send if they are // waiting for device bus internal buffer space // this only works if the observer is a blocking observer // this is DIFFERENT than the Java library which hanldes puts each bus buffer in own payload queue IMessageIOIO possibleNotifyableMessage = nextMessage as IMessageIOIO; // post notifications down our internal chain // This works only for observers on CaptureObservable_ // This does not post outbound messages to any observers on custom handlers if (possibleNotifyableMessage != null) { // this really exists for TX buffer calculation, // ie: IOIO internal resource management this.CaptureOutboundObservable_.HandleMessage(possibleNotifyableMessage); } LOG.Debug("T:" + OutgoingTask_.Id + " Executing: " + nextMessage); nextMessage.ExecuteMessage(this.OutProt_); } } } catch (System.Threading.ThreadAbortException e) { LOG.Error("T:" + OutgoingTask_.Id + " Probably aborted: (" + e.GetType() + ")" + e.Message); } catch (ObjectDisposedException e) { //// see this when steram is closed LOG.Error("T:" + OutgoingTask_.Id + " Probably closed outgoing Stream_: (ODE)" + e.Message); } catch (NullReferenceException e) { LOG.Error("T:" + OutgoingTask_ + " Caught Null Reference when sending message", e); } catch (IOException e) { LOG.Error("T:" + OutgoingTask_.Id + " Probably aborted incoming: (" + e.GetType() + ")" + e.Message); LOG.Error("T:" + OutgoingTask_.Id + e.StackTrace); } catch (Exception e) { LOG.Error("T:" + OutgoingTask_.Id + " Probably stopping outgoing: (" + e.GetType() + ")" + e.Message); } finally { // we don't play swith Stream_ since we didn't create it LOG.Debug("T:" + OutgoingTask_.Id + " Throwing thread cancel to make sure outgoing thread stopped"); // this is redundant if we got here because of thread stop this.CancelTokenSource_.Cancel(); // debugger will always stop here in unit tests if test dynamically determines what Port_ ot use // just hit continue in the debugger this.CancelTokenSource_.Token.ThrowIfCancellationRequested(); // should tell OutProt_ to shut down this.OutProt_ = null; this.OutgoingTask_ = null; } }
/// <summary> /// the one method subclass ned to implement /// </summary> /// <param name="message"></param> public abstract void HandleMessage(IMessageIOIO message);