private void SocketAsyncEventArgs_SendComplete(object sender, SocketAsyncEventArgs e)
        {
#if Matrix_Diagnostics
            InstanceMonitor monitor = Monitor;
            if (monitor != null && monitor.IsReportAllowed)
            {
                monitor.Info(string.Format("Send complete, sender [{0}].", sender != null ? sender.ToString() : string.Empty));
            }
#endif

            e.Completed -= new EventHandler <SocketAsyncEventArgs>(SocketAsyncEventArgs_SendComplete);

            AsyncMessageSendInfo sendInfo = (AsyncMessageSendInfo)e.UserToken;
            if (sendInfo.ConfirmationEvent != null)
            {// Signal any waiter, we sent the message.
                sendInfo.ConfirmationEvent.Set();
            }

            e.Dispose();

#if Matrix_Diagnostics
            if (Monitor.IsReportAllowed)
            {
                Monitor.Info(this.ToString() + " message send complete [" + sendInfo.Message.ToString() + "]");
            }
#endif

            AsyncMessageSendDelegate delegateInstance = SendAsyncCompleteEvent;
            if (delegateInstance != null)
            {
                delegateInstance(this, sendInfo);
            }
        }
        /// <summary>
        /// Send a message, asynchronously.
        /// </summary>
        /// <param name="message">The message being sent.</param>
        /// <param name="requestConfirm">Should we wait for a confirmation, the </param>
        /// <returns>The id of the send message, or negative value (InvalidSendIndex / -1) if send failed.</returns>
        public long SendAsync(object message, TimeSpan?requestConfirmTimeout)
        {
#if Matrix_Diagnostics
            InstanceMonitor monitor = Monitor;
            if (monitor != null && monitor.IsReportAllowed)
            {
                monitor.Info(string.Format("Async sending message [{0}].", message.ToString()));
            }
#endif

            System.Net.Sockets.Socket socket = _socket;
            if (IsConnected == false || socket == null)
            {
#if Matrix_Diagnostics
                Monitor.OperationError("Communicator can not send message [" + message.ToString() + "] since not connected.");
#endif
                return(InvalidSendIndex);
            }

            ISerializer serializer = _serializer;
            if (serializer == null)
            {
                return(InvalidSendIndex);
            }

            // Event used for confirmed calls
            ManualResetEvent sendCompleteEvent = null;
            if (requestConfirmTimeout.HasValue)
            {
                sendCompleteEvent = new ManualResetEvent(false);
            }

            AsyncMessageSendInfo messageSendInfo = new AsyncMessageSendInfo()
            {
                Id                = PendingSendId,
                Socket            = socket,
                Message           = message,
                ConfirmationEvent = sendCompleteEvent,
            };

            SocketAsyncEventArgs e = new SocketAsyncEventArgs();
            e.UserToken  = messageSendInfo;
            e.Completed += new EventHandler <SocketAsyncEventArgs>(SocketAsyncEventArgs_SendComplete);

            messageSendInfo.Stream = new MemoryStream();
            if (serializer.Serialize(messageSendInfo.Stream, message) == false)
            {
                messageSendInfo.Dispose();
                return(InvalidSendIndex);
            }

            e.SetBuffer(messageSendInfo.Stream.GetBuffer(), 0, (int)messageSendInfo.Stream.Length);
            if (messageSendInfo.Socket.SendAsync(e) == false)
            {
                messageSendInfo.Dispose();
            }

            // Reaquire the event, to lessen the chance of [ObjectDisposedException]
            // when the connection is not established and we get errors on complete instantly.
            sendCompleteEvent = messageSendInfo.ConfirmationEvent;
            if (sendCompleteEvent != null)
            {
                try
                {
                    if (sendCompleteEvent.WaitOne(requestConfirmTimeout.Value) == false)
                    {
#if Matrix_Diagnostics
                        Monitor.OperationError("Communicator could not confirm message sent in assigned timeout.");
#endif
                        return(InvalidSendIndex);
                    }
                }
                catch (ObjectDisposedException)
                {
#if Matrix_Diagnostics
                    Monitor.OperationError("Communicator could not confirm message sent in assigned timeout, due to event disposed.");
#endif
                    return(InvalidSendIndex);
                }
            }

            return(messageSendInfo.Id);
        }
        /// <summary>
        /// Send a message, asynchronously.
        /// </summary>
        /// <param name="message">The message being sent.</param>
        /// <param name="requestConfirm">Should we wait for a confirmation, the </param>
        /// <returns>The id of the send message, or negative value (InvalidSendIndex / -1) if send failed.</returns>
        public long SendAsync(object message, TimeSpan? requestConfirmTimeout)
        {
            #if Matrix_Diagnostics
            InstanceMonitor monitor = Monitor;
            if (monitor != null && monitor.IsReportAllowed)
            {
                monitor.Info(string.Format("Async sending message [{0}].", message.ToString()));
            }
            #endif

            System.Net.Sockets.Socket socket = _socket;
            if (IsConnected == false || socket == null)
            {
            #if Matrix_Diagnostics
                Monitor.OperationError("Communicator can not send message [" + message.ToString() + "] since not connected.");
            #endif
                return InvalidSendIndex;
            }

            ISerializer serializer = _serializer;
            if (serializer == null)
            {
                return InvalidSendIndex;
            }

            // Event used for confirmed calls
            ManualResetEvent sendCompleteEvent = null;
            if (requestConfirmTimeout.HasValue)
            {
                sendCompleteEvent = new ManualResetEvent(false);
            }

            AsyncMessageSendInfo messageSendInfo = new AsyncMessageSendInfo() {
                                                                                  Id = PendingSendId,
                                                                                  Socket = socket,
                                                                                  Message = message,
                                                                                  ConfirmationEvent = sendCompleteEvent,
                                                                              };

            SocketAsyncEventArgs e = new SocketAsyncEventArgs();
            e.UserToken = messageSendInfo;
            e.Completed += new EventHandler<SocketAsyncEventArgs>(SocketAsyncEventArgs_SendComplete);

            messageSendInfo.Stream = new MemoryStream();
            if (serializer.Serialize(messageSendInfo.Stream, message) == false)
            {
                messageSendInfo.Dispose();
                return InvalidSendIndex;
            }

            e.SetBuffer(messageSendInfo.Stream.GetBuffer(), 0, (int)messageSendInfo.Stream.Length);
            if (messageSendInfo.Socket.SendAsync(e) == false)
            {
                messageSendInfo.Dispose();
            }

            // Reaquire the event, to lessen the chance of [ObjectDisposedException]
            // when the connection is not established and we get errors on complete instantly.
            sendCompleteEvent = messageSendInfo.ConfirmationEvent;
            if (sendCompleteEvent != null)
            {
                try
                {
                    if (sendCompleteEvent.WaitOne(requestConfirmTimeout.Value) == false)
                    {
            #if Matrix_Diagnostics
                        Monitor.OperationError("Communicator could not confirm message sent in assigned timeout.");
            #endif
                        return InvalidSendIndex;
                    }
                }
                catch (ObjectDisposedException)
                {
            #if Matrix_Diagnostics
                    Monitor.OperationError("Communicator could not confirm message sent in assigned timeout, due to event disposed.");
            #endif
                    return InvalidSendIndex;
                }
            }

            return messageSendInfo.Id;
        }