/// <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); } }
public void Identify(bool enabled) { IdentifyDevice.Set identify = new IdentifyDevice.Set(); identify.IdentifyEnabled = enabled; socket.SendRdm(identify, Address, Id); }