/// <summary> /// Write a frame and wait for its receipt frame before returning. /// /// This method does not add a receipt header if it is not included already. /// If the receipt header is not in the frame headers then it returns after sending the message. /// </summary> /// <param name="frame"></param> /// <param name="cancellationToken"></param> /// <returns></returns> public async Task WriteAsync(Frame frame, CancellationToken cancellationToken) { string receipt = frame.Command == StompCommands.Connect ? _connectReceiptHeader : frame.GetHeader(StompHeaders.Receipt); if (receipt == null) { await _writer.WriteAsync(frame, cancellationToken); } else { TaskCompletionSource<object> receiptWaiter = new TaskCompletionSource<object>(); Task task = receiptWaiter.Task; _receiptWaiters[receipt] = receiptWaiter; do { await _writer.WriteAsync(frame, cancellationToken); } while (await Task.WhenAny(task, Task.Delay(_retryInterval, cancellationToken)) != task && !task.IsFaulted && !task.IsCanceled); if (task.IsFaulted) throw task.Exception; if (task.IsCanceled) throw new OperationCanceledException(cancellationToken); } }
private void OnNext(Frame frame) { string receiptId = frame.Command == StompCommands.Receipt ? frame.GetHeader(StompHeaders.ReceiptId) : frame.Command == StompCommands.Connected ? _connectReceiptHeader : null; if(receiptId != null) { TaskCompletionSource<object> tcs; if (_receiptWaiters.TryGetValue(receiptId, out tcs)) { tcs.TrySetResult(null); _receiptWaiters.TryRemove(receiptId, out tcs); } } }