Example #1
0
        private static Task <T> FromAsync <T>(Func <AsyncCallback, IAsyncResult> begin, Func <IAsyncResult, T> end)
        {
            var tcs = new DispatchingTaskCompletionSource <T>();

            try
            {
                var result = begin(ar =>
                {
                    if (!ar.CompletedSynchronously)
                    {
                        CompleteAsync(tcs, ar, end);
                    }
                });

                if (result.CompletedSynchronously)
                {
                    CompleteAsync(tcs, result, end);
                }
            }
            catch (Exception ex)
            {
                tcs.TrySetException(ex);
            }

            return(tcs.Task);
        }
Example #2
0
 private static void CompleteAsync <T>(DispatchingTaskCompletionSource <T> tcs, IAsyncResult ar, Func <IAsyncResult, T> end)
 {
     try
     {
         tcs.TrySetResult(end(ar));
     }
     catch (OperationCanceledException)
     {
         tcs.TrySetCanceled();
     }
     catch (Exception ex)
     {
         tcs.TrySetException(ex);
     }
 }
Example #3
0
        private void ResolveTransport(IConnection connection, string data, CancellationToken disconnectToken, DispatchingTaskCompletionSource <object> tcs, int index)
        {
            // Pick the current transport
            IClientTransport transport = _transports[index];

            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.
                    var next = index + 1;
                    if (next < _transports.Count && !(ex is StartException))
                    {
                        // Try the next transport
                        ResolveTransport(connection, data, disconnectToken, tcs, next);
                    }
                    else
                    {
                        // If there's nothing else to try then just fail
                        tcs.TrySetException(ex);
                    }
                }
                else
                {
                    // Set the active transport
                    _transport = transport;

                    // Complete the process
                    tcs.TrySetResult(null);
                }
            },
                                                                            TaskContinuationOptions.ExecuteSynchronously);
        }
Example #4
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);
        }
Example #5
0
        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);
        }
Example #6
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);
        }