private static void ContinueAsync <T>(Task <T> task, DispatchingTaskCompletionSource <object> tcs)
 {
     task.ContinueWithPreservedCulture(t =>
     {
         if (t.IsFaulted)
         {
             tcs.TrySetUnwrappedException(t.Exception);
         }
         else if (t.IsCanceled)
         {
             tcs.TrySetCanceled();
         }
         else
         {
             tcs.TrySetResult(t.Result);
         }
     });
 }
Beispiel #2
0
        private Task StartTransport()
        {
            return(_transport.Start(this, _connectionData, _disconnectCts.Token)
                   .RunSynchronously(() =>
            {
                // NOTE: We have tests that rely on this state change occuring *BEFORE* the start task is complete
                ChangeState(ConnectionState.Connecting, ConnectionState.Connected);

                // Now that we're connected complete the start task that the
                // receive queue is waiting on
                _startTcs.TrySetResult(null);

                // Start the monitor to check for server activity
                _lastMessageAt = DateTime.UtcNow;
                _lastActiveAt = DateTime.UtcNow;
                Monitor.Start();
            })
                   // Don't return until the last receive has been processed to ensure messages/state sent in OnConnected
                   // are processed prior to the Start() method task finishing
                   .Then(() => _lastQueuedReceiveTask));
        }
Beispiel #3
0
        private void SendImpl(IEnumerator <IGrouping <string, Message> > enumerator, DispatchingTaskCompletionSource <object> taskCompletionSource)
        {
send:

            if (!enumerator.MoveNext())
            {
                taskCompletionSource.TrySetResult(null);
            }
            else
            {
                IGrouping <string, Message> group = enumerator.Current;

                // Get the channel index we're going to use for this message
                int index = (int)((uint)_sipHashBasedComparer.GetHashCode(group.Key) % StreamCount);

                Debug.Assert(index >= 0, "Hash function resulted in an index < 0.");

                Task sendTask = StreamManager.Send(index, group.ToArray()).Catch(_trace);

                if (sendTask.IsCompleted)
                {
                    try
                    {
                        sendTask.Wait();

                        goto send;
                    }
                    catch (Exception ex)
                    {
                        taskCompletionSource.SetUnwrappedException(ex);
                    }
                }
                else
                {
                    sendTask.Then((enumer, tcs) => SendImpl(enumer, tcs), enumerator, taskCompletionSource)
                    .ContinueWithNotComplete(taskCompletionSource);
                }
            }
        }
 private void CompleteStart()
 {
     Dispatch(() => _initializationTask.TrySetResult(null));
     _tokenCleanup.Dispose();
 }
Beispiel #5
0
        private void ResolveTransport(
            IConnection connection,
            string data,
            CancellationToken disconnectToken,
            DispatchingTaskCompletionSource <object> tcs,
            Exception lastError,
            int index)
        {
            IClientTransport transport = null;
            var next = index;

            // Pick the current transport
            while (next < _transports.Count && transport == null)
            {
                var candidateTransport = _transports[next++];

                // If the current transport is WebSockets and it's not supported by the server, try the next transport.
                if (_tryWebSockets || !"webSockets".Equals(candidateTransport.Name, StringComparison.Ordinal))
                {
                    transport = candidateTransport;
                }
            }

            if (transport is null)
            {
                // If there's nothing else to try, then just fail with the error from the last transport.
                // For the lastError to be null, the AutoTransport must have been initialized with an empty transport list or only WebSockets.
                tcs.TrySetException(lastError ?? new Exception(Resources.Error_NoCompatibleTransportFound));
                return;
            }

            transport.Start(connection, data, disconnectToken).ContinueWith(task =>
            {
                if (task.IsFaulted || task.IsCanceled)
                {
                    Exception ex;
                    if (task.IsCanceled)
                    {
                        ex = new OperationCanceledException(Resources.Error_TaskCancelledException);
                    }
                    else
                    {
                        ex = task.Exception.GetBaseException();
                    }

                    connection.Trace(TraceLevels.Events, "Auto: Failed to connect to using transport {0}. {1}", transport.Name, ex);

                    // If that transport fails to initialize, then fallback.
                    // If it is that /start request that failed, do not fallback.
                    if (ex is StartException)
                    {
                        tcs.TrySetException(ex);
                    }
                    else
                    {
                        // Try the next transport
                        ResolveTransport(connection, data, disconnectToken, tcs, ex, next);
                    }
                }
                else
                {
                    // Set the active transport
                    _transport = transport;

                    // Complete the process
                    tcs.TrySetResult(null);
                }
            },
                                                                            TaskContinuationOptions.ExecuteSynchronously);
        }
        public Task <TResult> Invoke <TResult, TProgress>(string method, Action <TProgress> onProgress, params object[] args)
        {
            if (method == null)
            {
                throw new ArgumentNullException("method");
            }

            if (args == null)
            {
                throw new ArgumentNullException("args");
            }

            var tokenifiedArguments = new JToken[args.Length];

            for (int i = 0; i < tokenifiedArguments.Length; i++)
            {
                tokenifiedArguments[i] = args[i] != null
                    ? JToken.FromObject(args[i], JsonSerializer)
                    : JValue.CreateNull();
            }

            var tcs        = new DispatchingTaskCompletionSource <TResult>();
            var callbackId = _connection.RegisterCallback(result =>
            {
                if (result != null)
                {
                    if (result.Error != null)
                    {
                        if (result.IsHubException.HasValue && result.IsHubException.Value)
                        {
                            // A HubException was thrown
                            tcs.TrySetException(new HubException(result.Error, result.ErrorData));
                        }
                        else
                        {
                            tcs.TrySetException(new InvalidOperationException(result.Error));
                        }
                    }
                    else
                    {
                        try
                        {
                            if (result.State != null)
                            {
                                foreach (var pair in result.State)
                                {
                                    this[pair.Key] = pair.Value;
                                }
                            }

                            if (result.ProgressUpdate != null)
                            {
                                onProgress(result.ProgressUpdate.Data.ToObject <TProgress>(JsonSerializer));
                            }
                            else if (result.Result != null)
                            {
                                tcs.TrySetResult(result.Result.ToObject <TResult>(JsonSerializer));
                            }
                            else
                            {
                                tcs.TrySetResult(default(TResult));
                            }
                        }
                        catch (Exception ex)
                        {
                            // If we failed to set the result for some reason or to update
                            // state then just fail the tcs.
                            tcs.TrySetUnwrappedException(ex);
                        }
                    }
                }
                else
                {
                    tcs.TrySetCanceled();
                }
            });

            var hubData = new HubInvocation
            {
                Hub        = _hubName,
                Method     = method,
                Args       = tokenifiedArguments,
                CallbackId = callbackId
            };

            if (_state.Count != 0)
            {
                hubData.State = _state;
            }

            var value = _connection.JsonSerializeObject(hubData);

            _connection.Send(value).ContinueWith(task =>
            {
                if (task.IsCanceled)
                {
                    _connection.RemoveCallback(callbackId);
                    tcs.TrySetCanceled();
                }
                else if (task.IsFaulted)
                {
                    _connection.RemoveCallback(callbackId);
                    tcs.TrySetUnwrappedException(task.Exception);
                }
            },
                                                 TaskContinuationOptions.NotOnRanToCompletion);

            return(tcs.Task);
        }
Beispiel #7
0
        public Task <JSONNode> Invoke(string method, Action <JSONNode> onProgress, params object[] args)
        {
            if (method == null)
            {
                throw new ArgumentNullException("method");
            }

            if (args == null)
            {
                throw new ArgumentNullException("args");
            }

            JSONArray ArgsArray = new JSONArray();

            for (int i = 0; i < args.Length; i++)
            {
                ArgsArray.Add(JSON.FromData(args[i]));
            }

            var tcs        = new DispatchingTaskCompletionSource <JSONNode>();
            var callbackId = _connection.RegisterCallback(result =>
            {
                if (result != null)
                {
                    if (result.Error != null)
                    {
                        if (result.IsHubException)
                        {
                            // A HubException was thrown
                            tcs.TrySetException(new HubException(result.Error, result.ErrorData));
                        }
                        else
                        {
                            tcs.TrySetException(new InvalidOperationException(result.Error));
                        }
                    }
                    else
                    {
                        try
                        {
                            if (result.State != null)
                            {
                                foreach (var pair in result.State)
                                {
                                    this[pair.Key] = pair.Value;
                                }
                            }

                            if (result.ProgressUpdate != null)
                            {
                                onProgress?.Invoke(result.ProgressUpdate.Data);
                            }
                            else if (result.Result != null)
                            {
                                tcs.TrySetResult(result.Result);
                            }
                            else
                            {
                                tcs.TrySetResult(new JSONNonexistent());
                            }
                        }
                        catch (Exception ex)
                        {
                            // If we failed to set the result for some reason or to update
                            // state then just fail the tcs.
                            tcs.TrySetUnwrappedException(ex);
                        }
                    }
                }
                else
                {
                    tcs.TrySetCanceled();
                }
            });

            var hubData = new HubInvocation
            {
                Hub        = _hubName,
                Method     = method,
                Args       = ArgsArray,
                CallbackId = callbackId
            };

            if (_state.Count != 0)
            {
                hubData.State = _state;
            }

            var value = hubData.ToJson().Serialize();

            _connection.Send(value).ContinueWith(task =>
            {
                if (task.IsCanceled)
                {
                    _connection.RemoveCallback(callbackId);
                    tcs.TrySetCanceled();
                }
                else if (task.IsFaulted)
                {
                    _connection.RemoveCallback(callbackId);
                    tcs.TrySetUnwrappedException(task.Exception);
                }
            },
                                                 TaskContinuationOptions.NotOnRanToCompletion);

            return(tcs.Task);
        }