private void SetMessageId(Message message) { if (message.MustBeReliable || message.PreferReliable) { message.Header.MessageId = MessageSerializer.GetNextMessageId(ref this.nextReliableMessageId); } else { message.Header.MessageId = MessageSerializer.GetNextMessageId(ref this.nextMessageId); } }
private Task <bool> SendMessage(Message message, bool isResponse, bool requestingResponse, int responseTimeout, out Task <Message> responseTask) { string callCategory = null; #if TRACE int c = GetNextCallId(); callCategory = String.Format("{1}:{2} {3}:Send({0})", message, this.typeName, this.connectionId, c); #endif Trace.WriteLineIf(NTrace.TraceVerbose, "Entering", callCategory); responseTask = null; TaskCompletionSource <bool> tcs = new TaskCompletionSource <bool> (message); if (message == null) { throw new ArgumentNullException("message"); } if (!IsConnected) { Trace.WriteLineIf(NTrace.TraceVerbose, "Exiting (not connected)", callCategory); tcs.SetResult(false); if (requestingResponse) { var responseTcs = new TaskCompletionSource <Message>(); responseTcs.SetCanceled(); responseTask = responseTcs.Task; } return(tcs.Task); } SocketAsyncEventArgs eargs = null; #if NET_4 if (!writerAsyncArgs.TryPop(out eargs)) { while (eargs == null) { int count = bufferCount; if (count == sendBufferLimit) { Trace.WriteLineIf(NTrace.TraceVerbose, "Waiting for writer args", callCategory); SpinWait wait = new SpinWait(); while (!writerAsyncArgs.TryPop(out eargs)) { wait.SpinOnce(); } } else if (count == Interlocked.CompareExchange(ref bufferCount, count + 1, count)) { Trace.WriteLineIf(NTrace.TraceVerbose, "Creating new writer args", callCategory); eargs = new SocketAsyncEventArgs(); eargs.SetBuffer(new byte[1024], 0, 1024); eargs.Completed += ReliableSendCompleted; } } } #else while (eargs == null) { lock (writerAsyncArgs) { if (writerAsyncArgs.Count != 0) { eargs = writerAsyncArgs.Pop(); } else if (bufferCount != sendBufferLimit) { bufferCount++; eargs = new SocketAsyncEventArgs(); eargs.SetBuffer(new byte[1024], 0, 1024); eargs.Completed += ReliableSendCompleted; } } } #endif #if !SILVERLIGHT eargs.AcceptSocket = null; #endif Trace.WriteLineIf(NTrace.TraceVerbose, "Have writer args", callCategory); bool sent; lock (this.sendSync) { if (message.Header == null) { message.Header = new MessageHeader(); } message.Header.MessageId = MessageSerializer.GetNextMessageId(ref this.nextMessageId); if (requestingResponse) { responseTask = Responses.SendFor(message, tcs.Task, responseTimeout); } MessageSerializer slzr = this.serializer; if (slzr == null) { int sp = Interlocked.Decrement(ref this.pendingAsync); Trace.WriteLineIf(NTrace.TraceVerbose, String.Format("Decrement pending: {0}", sp), callCategory); #if !NET_4 lock (writerAsyncArgs) #endif writerAsyncArgs.Push(eargs); Trace.WriteLineIf(NTrace.TraceVerbose, "Exiting (serializer is null, probably disconnecting)", callCategory); tcs.SetResult(false); return(tcs.Task); } int length; byte[] buffer = slzr.GetBytes(message, out length, eargs.Buffer); eargs.SetBuffer(buffer, 0, length); eargs.UserToken = new KeyValuePair <NetworkConnection, TaskCompletionSource <bool> > (this, tcs); int p = Interlocked.Increment(ref this.pendingAsync); Trace.WriteLineIf(NTrace.TraceVerbose, String.Format("Increment pending: {0}", p), callCategory); if (!IsConnected) { Interlocked.Decrement(ref this.pendingAsync); Trace.WriteLineIf(NTrace.TraceVerbose, String.Format("Decrement pending: {0}", p), callCategory); #if !NET_4 lock (writerAsyncArgs) #endif writerAsyncArgs.Push(eargs); tcs.SetResult(false); return(tcs.Task); } Trace.WriteLineIf(NTrace.TraceVerbose, "Sending", callCategory); sent = !this.reliableSocket.SendAsync(eargs); } if (sent) { Trace.WriteLineIf(NTrace.TraceVerbose, "Send completed synchronously", callCategory); ReliableSendCompleted(this.reliableSocket, eargs); } Trace.WriteLineIf(NTrace.TraceVerbose, "Exiting", callCategory); return(tcs.Task); }