// This method will not catch exceptions so the BackgroundThread base class will receive them, // raise a "Failure" and trigger a reconnect. protected override void ThreadWorker(CancellationToken cancellationToken) { try { Debug.Assert(_context.Transport != null, "_context.Transport != null"); ITransport transport = _context.Transport; // Iterate over all queued items (will block if the queue is empty) foreach (QueueItem queueItem in _queue.GetConsumingEnumerable(cancellationToken)) { IOutgoingMessage <IOutgoingMessageType> message = queueItem.Message; IOutgoingMessageType messageType = queueItem.MessageType; if (_logger.IsEnabled(LogLevel.Debug)) { string?parametersOverview = message.GetParametersOverview(); _logger.LogDebug("Sending {messageName} message ({parameters})...", messageType.Name, parametersOverview ?? "no parameters"); } try { // Write message to transport stream messageType.WriteToTransport(message, transport, cancellationToken); queueItem.CompletionSource?.SetResult(null); } catch (Exception ex) { // If something went wrong during sending, tell the waiting tasks about it (so for example the GUI doesn't wait forever). queueItem.CompletionSource?.TrySetException(ex); // Send-thread should still fail throw; } } } catch { // When the loop was canceled or failed, cancel all remaining queue items SetQueueCancelled(); throw; } }
public QueueItem(IOutgoingMessage <IOutgoingMessageType> message, IOutgoingMessageType messageType, TaskCompletionSource <object?>?completionSource = null) { Message = message; MessageType = messageType; CompletionSource = completionSource; }