/// <summary>
        /// Prova ad inviare il messaggio specificato al servizio configurato con la specifica istanza di questa classe.
        /// </summary>
        /// <param name="message">La query o la reply da inviare al servizio di un nodo vicino.</param>
        /// <param name="detection">L'eventuale istante di rilevamento del vicino.</param>
        /// <returns>true se non si sono vericati errori durante l'invio della query; in caso contrario, false.</returns>
        /// <remarks>
        /// Se si verificano errori durante la trasmissione del messaggio al servizio, questo metodo restituisce false
        /// e imposta il valore predefinito di un oggetto DateTime come istante di rilevazione, pertanto il valore non
        /// deve essere considerato. Invece, se il metodo restituisce true, vuol dire che non è avvenuto nessun errore
        /// durante la trasmissione del messaggio e quindi l'istante di rilevazione del servizio è corretto.
        /// </remarks>
        private bool TrySendMessage(MessageData message, out DateTime detection)
        {
            lock (m_SyncLock)
            {
                if (m_ProxyClosed || m_BindingConfig == null || m_RemoteUri == null)
                {
                    detection = default(DateTime);
                    return false;
                }

                try
                {
                    if (m_InternalProxy == null)
                    {
                        ChannelFactory<IQueryReplyService> factory =
                            new ChannelFactory<IQueryReplyService>(m_BindingConfig, new EndpointAddress(m_RemoteUri));

                        m_InternalProxy = factory.CreateChannel();
                    }

                    if (message is QueryData)
                    {
                        WriteToLog("Dispatching query {0} to node {1}...", message.MsgId, m_TargetNodeId);

                        m_InternalProxy.Query(m_NodeId, message as QueryData);
                    }
                    else if (message is ReplyData)
                    {
                        WriteToLog("Dispatching reply {0} to node {1}...", message.MsgId, m_TargetNodeId);

                        m_InternalProxy.Reply(m_NodeId, message as ReplyData);
                    }
                    else
                    {
                        detection = default(DateTime);
                        return false;
                    }

                    detection = DateTime.Now;
                    return true;
                }
                catch
                {
                    if (m_InternalProxy != null)
                    {
                        ICommunicationObject proxy = m_InternalProxy as ICommunicationObject;

                        if (proxy.State == CommunicationState.Faulted)
                        {
                            proxy.Abort();
                            m_InternalProxy = null;
                        }
                    }

                    detection = default(DateTime);
                    return false;
                }
            }
        }
        /// <summary>
        /// Inserisce il messaggio specificato nella coda di uscita di questo NeighborClient e restituisce true
        /// se il messaggio è stato effettivamente inserito in coda, altrimenti false se non è stato possibile
        /// aggiungere il messaggio perché la coda era piena.
        /// </summary>
        /// <param name="message">Il messaggio da inserire nella coda di uscita.</param>
        /// <returns>true se il messaggio è stato inserito in coda; in caso contrario, false.</returns>
        public bool Enqueue(MessageData message)
        {
            lock (m_SyncLock)
            {
                if (m_OutputQueue.Count == m_OutputQueueSize) return false;

                m_OutputQueue.Enqueue(message);
                Monitor.Pulse(m_SyncLock);   // notifica l'unico consumatore
            }

            return true;
        }