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