// 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); } }
// Run on its own thread, and invokes user code from it (task continuations) private void WriteFramesLoop() { if (LogAdapter.IsDebugEnabled) { LogAdapter.LogDebug(LogSource, "WriteFramesLoop starting"); } CommandToSend cmdToSend = null; _writeThreadRunning = true; try { var token = _threadCancelToken; while (!token.IsCancellationRequested) { _commandOutboxEvent.WaitOne(1000); // maybe it's better to _cancellationToken.Register(action) ? if (token.IsCancellationRequested) { break; // perf hit? } while (_commandOutbox.TryDequeue(out cmdToSend)) { FlushCommand(cmdToSend); } } if (LogAdapter.IsErrorEnabled) { LogAdapter.LogError(LogSource, "WriteFramesLoop exiting"); } } catch (ThreadAbortException) { // no-op } catch (Exception ex) { if (LogAdapter.IsErrorEnabled) { LogAdapter.LogError(LogSource, "WriteFramesLoop error. Last command " + cmdToSend.ToDebugInfo(), ex); } this.InitiateAbruptClose(ex).IntentionallyNotAwaited(); } finally { _writeThreadRunning = false; TryTriggerClean(); } }