コード例 #1
0
        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);
            }
        }