public static async Task InvokeAsync( this JsonRpc rpc, string targetName, IEnumerable <object> arguments, Action <Stream, CancellationToken> actionWithDirectStream, CancellationToken cancellationToken) { using (var mergedCancellation = CancellationTokenSource.CreateLinkedTokenSource(cancellationToken)) using (var stream = new ServerDirectStream()) { try { // send request by adding direct stream name to end of arguments var task = rpc.InvokeAsync(targetName, arguments.Concat(stream.Name).ToArray()); // if invoke throws an exception, make sure we raise cancellation. RaiseCancellationIfInvokeFailed(task, mergedCancellation, cancellationToken); // wait for asset source to respond await stream.WaitForDirectConnectionAsync(mergedCancellation.Token).ConfigureAwait(false); // run user task with direct stream actionWithDirectStream(stream, mergedCancellation.Token); // wait task to finish await task.ConfigureAwait(false); } catch (Exception ex) when(ReportUnlessCanceled(ex, cancellationToken)) { // important to use cancelationToken here rather than mergedCancellationToken. // there is a slight delay when merged cancellation token will be notified once cancellation token // is raised, it can cause one to be in cancelled mode and the other is not. here, one we // actually care is the cancellation token given in, not the merged cancellation token. cancellationToken.ThrowIfCancellationRequested(); throw; } } }
public static async Task InvokeAsync( this JsonRpc rpc, string targetName, IEnumerable <object> arguments, Func <Stream, CancellationToken, Task> funcWithDirectStreamAsync, CancellationToken cancellationToken) { try { using (var mergedCancellation = CancellationTokenSource.CreateLinkedTokenSource(cancellationToken)) using (var stream = new ServerDirectStream()) { // send request by adding direct stream name to end of arguments var task = rpc.InvokeAsync(targetName, arguments.Concat(stream.Name).ToArray()); // if invoke throws an exception, make sure we raise cancellation. RaiseCancellationIfInvokeFailed(task, mergedCancellation, cancellationToken); // wait for asset source to respond await stream.WaitForDirectConnectionAsync(mergedCancellation.Token).ConfigureAwait(false); // run user task with direct stream await funcWithDirectStreamAsync(stream, mergedCancellation.Token).ConfigureAwait(false); // wait task to finish await task.ConfigureAwait(false); } } catch (OperationCanceledException) { // if cancelled due to us, throw cancellation exception. cancellationToken.ThrowIfCancellationRequested(); // if canclled due to invocation is failed, rethrow merged cancellation throw; } }
public static async Task InvokeAsync( this JsonRpc rpc, string targetName, IEnumerable <object> arguments, Action <Stream, CancellationToken> actionWithDirectStream, CancellationToken cancellationToken) { using (var mergedCancellation = CancellationTokenSource.CreateLinkedTokenSource(cancellationToken)) using (var stream = new ServerDirectStream()) { try { // send request by adding direct stream name to end of arguments var task = rpc.InvokeAsync(targetName, arguments.Concat(stream.Name).ToArray()); // if invoke throws an exception, make sure we raise cancellation. RaiseCancellationIfInvokeFailed(task, mergedCancellation, cancellationToken); // wait for asset source to respond await stream.WaitForDirectConnectionAsync(mergedCancellation.Token).ConfigureAwait(false); // run user task with direct stream actionWithDirectStream(stream, mergedCancellation.Token); // wait task to finish await task.ConfigureAwait(false); } catch (Exception ex) when(ReportUnlessCanceled(ex, mergedCancellation.Token)) { cancellationToken.ThrowIfCancellationRequested(); throw; } } }
public static async Task <T> InvokeAsync <T>( this JsonRpc rpc, string targetName, IEnumerable <object> arguments, Func <Stream, CancellationToken, Task <T> > funcWithDirectStreamAsync, CancellationToken cancellationToken) { try { using (var mergedCancellation = CancellationTokenSource.CreateLinkedTokenSource(cancellationToken)) using (var stream = new ServerDirectStream()) { // send request to asset source var task = rpc.InvokeAsync(targetName, arguments.Concat(stream.Name).ToArray()); // if invoke throws an exception, make sure we raise cancellation. RaiseCancellationIfInvokeFailed(task, mergedCancellation, cancellationToken); // wait for asset source to respond await stream.WaitForDirectConnectionAsync(mergedCancellation.Token).ConfigureAwait(false); // run user task with direct stream var result = await funcWithDirectStreamAsync(stream, mergedCancellation.Token).ConfigureAwait(false); // wait task to finish await task.ConfigureAwait(false); return(result); } } catch (Exception ex) when(IsCancelled(ex)) { cancellationToken.ThrowIfCancellationRequested(); throw; } }
public static async Task <T> InvokeAsync <T>( this JsonRpc rpc, string targetName, IEnumerable <object> arguments, Func <Stream, CancellationToken, Task <T> > funcWithDirectStreamAsync, CancellationToken cancellationToken) { try { using (var mergedCancellation = CancellationTokenSource.CreateLinkedTokenSource(cancellationToken)) using (var stream = new ServerDirectStream()) { // send request to asset source var task = rpc.InvokeAsync(targetName, arguments.Concat(stream.Name).ToArray()); // if invoke throws an exception, make sure we raise cancellation. RaiseCancellationIfInvokeFailed(task, mergedCancellation, cancellationToken); // wait for asset source to respond await stream.WaitForDirectConnectionAsync(mergedCancellation.Token).ConfigureAwait(false); // run user task with direct stream var result = await funcWithDirectStreamAsync(stream, mergedCancellation.Token).ConfigureAwait(false); // wait task to finish await task.ConfigureAwait(false); return(result); } } catch (ObjectDisposedException) { // object disposed exception can be thrown from StreamJsonRpc if JsonRpc is disposed in the middle of read/write. // the way we added cancellation support to the JsonRpc which doesn't support cancellation natively // can cause this exception to happen. newer version supports cancellation token natively, but // we can't use it now, so we will catch object disposed exception and check cancellation token cancellationToken.ThrowIfCancellationRequested(); throw; } catch (OperationCanceledException) { // if cancelled due to us, throw cancellation exception. cancellationToken.ThrowIfCancellationRequested(); // if canclled due to invocation is failed, rethrow merged cancellation throw; } }
public static async Task <T> InvokeAsync <T>( this JsonRpc rpc, string targetName, IReadOnlyList <object> arguments, Func <Stream, CancellationToken, Task <T> > funcWithDirectStreamAsync, CancellationToken cancellationToken) { Task task = null; using (var mergedCancellation = CancellationTokenSource.CreateLinkedTokenSource(cancellationToken)) using (var stream = new ServerDirectStream()) { try { // send request to asset source task = rpc.InvokeWithCancellationAsync(targetName, arguments.Concat(stream.Name).ToArray(), cancellationToken); // if invoke throws an exception, make sure we raise cancellation. RaiseCancellationIfInvokeFailed(task, mergedCancellation, cancellationToken); // wait for asset source to respond await stream.WaitForDirectConnectionAsync(mergedCancellation.Token).ConfigureAwait(false); // run user task with direct stream var result = await funcWithDirectStreamAsync(stream, mergedCancellation.Token).ConfigureAwait(false); // wait task to finish await task.ConfigureAwait(false); return(result); } catch (Exception ex) when(ReportUnlessCanceled(ex, mergedCancellation.Token, cancellationToken)) { // important to use cancelationToken here rather than mergedCancellationToken. // there is a slight delay when merged cancellation token will be notified once cancellation token // is raised, it can cause one to be in cancelled mode and the other is not. here, one we // actually care is the cancellation token given in, not the merged cancellation token. cancellationToken.ThrowIfCancellationRequested(); // record reason why task got aborted. use NFW here since we don't want to // crash VS on explicitly killing OOP. task.Exception.ReportServiceHubNFW("JsonRpc Invoke Failed"); throw; } } }