private void RaiseStatusChanged() { var tmp = statusChanged; if (tmp != null) { eventScheduler.Schedule(() => tmp(this, new EventArgs())); } }
/// <summary> /// The pump for received messages. /// </summary> /// <param name="uri"> /// The uri. /// </param> /// <param name="cancellation"> /// The cancellation token source. /// </param> /// <returns> /// The observable stream of messages. /// </returns> private static IObservableSocket CreateObservableSocket(Uri uri, CancellationTokenSource cancellation) { var status = new ReplaySubject <ConnectionStatus>(1); var socket = new WebSocket4Net.WebSocket(uri.ToString()); var connected = new TaskCompletionSource <int>(); var dispatcher = new ConcurrentExclusiveSchedulerPair(); var sendScheduler = new TaskPoolScheduler(new TaskFactory(dispatcher.ExclusiveScheduler)); var receiveScheduler = new TaskPoolScheduler(new TaskFactory(dispatcher.ConcurrentScheduler)); Func <string, Task> send = message => { var tcs = new TaskCompletionSource <int>(); sendScheduler.Schedule( () => { try { if (socket.State != WebSocket4Net.WebSocketState.Open) { socket.Open(); } socket.Send(message); tcs.SetResult(0); } catch (Exception e) { tcs.SetException(e); } }); ; return(tcs.Task); }; socket.Open(); var incoming = Observable.Create <string>( observer => { status.OnNext(ConnectionStatus.Connecting); var completed = false; EventHandler <WebSocket4Net.MessageReceivedEventArgs> onMessage = (sender, args) => observer.OnNext(args.Message); EventHandler <ws::SuperSocket.ClientEngine.ErrorEventArgs> onError = (sender, args) => { observer.OnError(args.Exception); completed = true; cancellation.Cancel(); }; EventHandler onClosed = (sender, args) => cancellation.Cancel(); socket.MessageReceived += onMessage; socket.Error += onError; socket.Closed += onClosed; socket.Opened += (sender, args) => connected.TrySetResult(0); cancellation.Token.Register( () => { if (!completed) { observer.OnCompleted(); } socket.MessageReceived -= onMessage; socket.Error -= onError; socket.Closed -= onClosed; try { socket.Close(); } catch { // Ignore errors closing the socket. } dispatcher.Complete(); }); return(Disposable.Create(cancellation.Cancel)); }).SubscribeOn(receiveScheduler).Publish().RefCount(); return(new ObservableSocket(incoming, send, status, connected.Task)); }