Пример #1
0
        /// <summary>
        /// Initializes a new instance of the <see cref="ObservableClientWebSocket"/> class.
        /// </summary>
        /// <param name="uri">
        /// The uri.
        /// </param>
        /// <param name="cancellationToken">
        /// The cancellation token.
        /// </param>
        public ObservableClientWebSocket(Uri uri, CancellationToken cancellationToken)
        {
            this.uri = uri;

            this.status = new ReplaySubject <ConnectionStatus>(1);
            this.Status = this.status.AsObservable();

            this.sendActor    = new MutuallyExclusiveTaskExecutor();
            this.receiveActor = new MutuallyExclusiveTaskExecutor();

            this.cancellation = new CancellationTokenSource();
            cancellationToken.Register(this.cancellation.Cancel);

            this.sendMemoryStream      = new MemoryStream();
            this.sendEncoder           = new StreamWriter(this.sendMemoryStream, Utf8EncodingWithoutByteOrderMark);
            this.sendEncoder.AutoFlush = true;

            this.sendActor.Start(this.cancellation.Token).ContinueWith(
                _ =>
            {
                Debug.WriteLine("Send Actor completed: Status: {0}, Exception: {1}", _.Status, _.Exception);
                this.sendActor.Dispose();
                this.sendMemoryStream.Dispose();
                this.sendEncoder.Dispose();
            });

            this.receiveActor.Start(this.cancellation.Token).ContinueWith(
                _ =>
            {
                Debug.WriteLine("Receive Actor completed: Status: {0}, Exception: {1}", _.Status, _.Exception);
                this.receiveActor.Dispose();
            });

            this.Incoming = Observable.Create <string>(
                observer =>
            {
                if (this.cancellation.IsCancellationRequested)
                {
                    throw new OperationCanceledException();
                }

                var observerCancellation = new CancellationTokenSource();
                this.cancellation.Token.Register(
                    () =>
                {
                    observerCancellation.Cancel();
                    observer.OnCompleted();
                });
                this.receiveActor.Schedule(() => this.ReceivePump(observer, observerCancellation.Token));
                return(Disposable.Create(observerCancellation.Cancel));
            }).Publish().RefCount();
        }
Пример #2
0
        /// <summary>
        /// The socket send pump.
        /// </summary>
        /// <param name="socket">
        /// The socket.
        /// </param>
        /// <param name="uri">
        /// The uri.
        /// </param>
        /// <param name="cancellation">
        /// The cancellation.
        /// </param>
        /// <returns>
        /// The observer used to send messages to the socket.
        /// </returns>
        private static Func <string, Task> SocketSendPump(IWebSocket socket, Uri uri, CancellationTokenSource cancellation, TaskCompletionSource <int> connected)
        {
            var sender = new MutuallyExclusiveTaskExecutor();

            sender.Schedule(
                async() =>
            {
                try
                {
                    await socket.ConnectAsync(uri).AsTask(cancellation.Token).ConfigureAwait(false);
                    connected.TrySetResult(0);
                }
                catch
                {
                    cancellation.Cancel();
                }
            });

            var writer = new DataWriter(socket.OutputStream);

            sender.Run(cancellation.Token).ContinueWith(
                _ =>
            {
                if (_.Status != TaskStatus.RanToCompletion)
                {
                    cancellation.Cancel();
                }

                sender.Dispose();
            },
                CancellationToken.None);
            return(next => sender.Schedule(
                       async() =>
            {
                try
                {
                    writer.WriteString(next);
                    await writer.StoreAsync().AsTask(cancellation.Token).ConfigureAwait(false);
                }
                catch
                {
                    cancellation.Cancel();
                }
            }));
        }