/// <summary> /// This method is not yet finished. /// </summary> public virtual void WaitForConnect() { Conn_.WaitForConnect(); // Use the same cancel token for inbound and outbound CancelTokenSource_ = new CancellationTokenSource(); OutProt_ = new IOIOProtocolOutgoing(this.Conn_.GetOutputStream()); InProt_ = new IOIOProtocolIncoming(this.Conn_.GetInputStream(), this.InboundHandler_, CancelTokenSource_); // start the message pump OutgoingTask_ = new Task(run, CancelTokenSource_.Token, TaskCreationOptions.LongRunning); OutgoingTask_.Start(); // message sink has to be started before we can verify board version because the board staus is picked up by the sync //Joe's COM4 @ 115200 spits out HW,BootLoader,InterfaceVersion: IOIOSPRK0016IOIO0311IOIO0500 initBoardVersion(); //checkInterfaceVersion(); }
////////////////////////////////////////////////////////// //// 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; } }