public async Task <object> SendAsync(Packet packet) { if (packet.GetState() == PacketState.Cancelled) { throw new CancelledException(); } _queue.Add(packet); if (_state != SocketState.Connected) { var sendTask = packet.SendSubject.Amb(Observable.Timer(TimeSpan.FromMilliseconds(120 * 1000)).Select <long, Dictionary <string, object> >(x => null)).Where(x => x != null).Take(1).ToTask(); var cancelTask = packet.CancelObs.Amb(Observable.Timer(TimeSpan.FromMilliseconds(120 * 1000)).Select <long, Unit>(x => Unit.Default)).Take(1).ToTask(); var firstFinishedTask = await Task.WhenAny(sendTask, cancelTask); if (firstFinishedTask == cancelTask) { throw new CancelledException(); } return(await sendTask); } var timeout = packet.GetTimeout(_options.ReplyTimeout); var d = Observable.Return <Reply>(null); var replyTask = _reply.Amb(Observable.Timer(TimeSpan.FromMilliseconds(timeout)).Select <long, Reply>(x => null)).Where(x => x != null && x.Id == packet.Id).Take(1).ToTask(); var cancelTask2 = packet.CancelObs.Amb(Observable.Timer(TimeSpan.FromMilliseconds(timeout + 1)).Select <long, Unit>(x => Unit.Default)).Take(1).ToTask(); var closeTask = _close.Amb(Observable.Timer(TimeSpan.FromMilliseconds(timeout + 1)).Select <long, object>(x => new object())).Take(1).ToTask(); var race = Task.WhenAny(replyTask, cancelTask2, closeTask);//.ContinueWith(finishedTask => _send.OnNext(race); packet.SetState(PacketState.Sending); _ = SendPacketInnerAsync(packet); var finishTask = await race; if (finishTask == replyTask) { _queue.TryRemove(packet); if (replyTask.Result.Error != null) { throw replyTask.Result.Error; } packet.SendSubject.OnNext(replyTask.Result.Result); return(replyTask.Result.Result); } else if (finishTask == cancelTask2) { throw new CancelledException(); } else if (finishTask == closeTask) { if (!_queue.Contains(packet)) { return(null); } packet.SetState(PacketState.Pending); return(await SendAsync(packet)); } else { return(null); } }