// [MethodImpl(MethodImplOptions.AggressiveInlining)] private void FlushCommand(CommandToSend cmdToSend) { if (_threadCancelToken.IsCancellationRequested) { if (cmdToSend.Tcs != null) { cmdToSend.Tcs.TrySetCanceled(); } return; } var token = _threadCancelToken; if (!cmdToSend.Immediately) { _waitingServerReply.Wait(token); // Contention sadly required by the server/amqp } // The command will signal that we can send more commands... cmdToSend.Prepare(cmdToSend.ExpectsReply ? _waitingServerReply : null); if (cmdToSend.ExpectsReply) // enqueues as awaiting a reply from the server { _waitingServerReply.Reset(); // cannot send anything else var queue = cmdToSend.Channel == 0 ? _awaitingReplyQueue : _conn.ResolveChannel(cmdToSend.Channel)._awaitingReplyQueue; queue.Enqueue(cmdToSend); } // writes to socket var frameWriter = cmdToSend.OptionalArg as IFrameContentWriter; if (frameWriter != null) { frameWriter.Write(_amqpWriter, cmdToSend.Channel, cmdToSend.ClassId, cmdToSend.MethodId, cmdToSend.OptionalArg); } else { cmdToSend.commandGenerator(_amqpWriter, cmdToSend.Channel, cmdToSend.ClassId, cmdToSend.MethodId, cmdToSend.OptionalArg); } // if writing to socket is enough, set as complete if (!cmdToSend.ExpectsReply) { cmdToSend.RunReplyAction(0, 0, null); } }
// Run on its own thread, and invokes user code from it (task continuations) private void WriteFramesLoop() { if (LogAdapter.ExtendedLogEnabled) { LogAdapter.LogDebug("ConnectionIO", "WriteFramesLoop starting"); } CommandToSend cmdToSend = null; try { var token = _threadCancelToken; while (!token.IsCancellationRequested) { _commandOutboxEvent.WaitOne(1000); // maybe it's better to _cancellationToken.Register(action) ? while (_commandOutbox.TryDequeue(out cmdToSend)) { _waitingServerReply.Wait(token); // Contention sadly required by the server/amqp // The command will signal that we can send more commands... cmdToSend.Prepare(cmdToSend.ExpectsReply ? _waitingServerReply : null); if (cmdToSend.ExpectsReply) // enqueues as awaiting a reply from the server { _waitingServerReply.Reset(); // cannot send anything else var queue = cmdToSend.Channel == 0 ? _awaitingReplyQueue : _conn.ResolveChannel(cmdToSend.Channel)._awaitingReplyQueue; queue.Enqueue(cmdToSend); } // writes to socket var frameWriter = cmdToSend.OptionalArg as IFrameContentWriter; if (frameWriter != null) { frameWriter.Write(_amqpWriter, cmdToSend.Channel, cmdToSend.ClassId, cmdToSend.MethodId, cmdToSend.OptionalArg); } else { cmdToSend.commandGenerator(_amqpWriter, cmdToSend.Channel, cmdToSend.ClassId, cmdToSend.MethodId, cmdToSend.OptionalArg); } // if writing to socket is enough, set as complete if (!cmdToSend.ExpectsReply) { cmdToSend.RunReplyAction(0, 0, null).IntentionallyNotAwaited(); } } } LogAdapter.LogError("ConnectionIO", "WriteFramesLoop exiting"); } catch (ThreadAbortException) { // no-op } catch (Exception ex) { LogAdapter.LogError("ConnectionIO", "WriteFramesLoop error. Last command " + cmdToSend.ToDebugInfo(), ex); this.InitiateAbruptClose(ex); } }