예제 #1
0
        /// <summary>
        /// Processes the transaction queue and determines what transactions can be sent to their destination.
        /// </summary>
        /// <remarks>
        /// This function ensures that only a single transaction is sent to each DMX port every 20ms. Any more
        /// transactions per port and the device might become flooded.
        /// </remarks>
        /// <param name="state">Thread State</param>
        private void Retry(object state)
        {
            try
            {
                DateTime              timeStamp          = DateTime.Now;
                List <Transaction>    failedTransactions = new List <Transaction>();
                HashSet <Transaction> retryTransactions  = new HashSet <Transaction>(new TransactionUniverseComparer());
                int droppedPackets = 0;

                lock (transactionQueue)
                {
                    //Go through all queued transactions and determine what can be sent again.
                    foreach (Transaction transaction in transactionQueue.Values)
                    {
                        //Only process this transaction if it has exceeded the retry interval.
                        if (transaction.LastAttempt == DateTime.MinValue || timeStamp.Subtract(transaction.LastAttempt) > RetryInterval)
                        {
                            //We only send one packet per retry to each unique DMX port.
                            //The retryTransactions hash set is used to ensure only one transaction is sent to each port. The rest have to wait.
                            if (transaction.Attempts > RetryAttempts)
                            {
                                failedTransactions.Add(transaction);
                            }
                            else if (!retryTransactions.Contains(transaction))
                            {
                                //If we have already tried to send this transaction then increment the dropped packet count.
                                if (transaction.Attempts != 0)
                                {
                                    droppedPackets++;
                                }

                                //Queue this transaction for sending
                                retryTransactions.Add(transaction);
                                transaction.Attempts++;
                                transaction.LastAttempt = timeStamp;
                            }
                        }
                    }
                }

                foreach (Transaction transaction in retryTransactions)
                {
                    try
                    {
                        socket.SendRdm(transaction.Packet, transaction.TargetAddress, transaction.TargetId);
                    }
                    catch (ObjectDisposedException)
                    {
                        //The socket is no longer usable.
                        Dispose();
                        break;
                    }
                    catch (SocketException)
                    {
                        //If the connection has failed, remove the transaction from the queue to prevent further communications.
                        failedTransactions.Add(transaction);
                    }
                }

                PacketsDropped     += droppedPackets + failedTransactions.Count;
                TransactionsFailed += failedTransactions.Count;

                lock (transactionQueue)
                {
                    //Remove all transactions that have permanently failed.
                    foreach (Transaction transaction in failedTransactions)
                    {
                        transactionQueue.Remove(transaction.Id);
                    }

                    if (retryTimer != null)
                    {
                        retryTimer.Change(TransmitInterval, TimeSpan.Zero);
                    }
                }
            }
            catch (Exception ex)
            {
                //If an exception occurs, log the error but do not process any more of the queue.
                RaiseUnhandledException(ex);
            }
        }
예제 #2
0
 public void Identify(bool enabled)
 {
     IdentifyDevice.Set identify = new IdentifyDevice.Set();
     identify.IdentifyEnabled = enabled;
     socket.SendRdm(identify, Address, Id);
 }