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); } }); }
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)); }
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(); }
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); }
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); }