protected override async ValueTask <IComputed <T> > ComputeAsync( InterceptedInput input, IComputed <T>?existing, CancellationToken cancellationToken) { var tag = VersionGenerator.Next(); var computed = CreateComputed(input, tag); try { using var _ = Computed.ChangeCurrent(computed); var result = input.InvokeOriginalFunction(cancellationToken); if (input.Method.ReturnsValueTask) { var output = await((ValueTask <T>)result).ConfigureAwait(false); computed.TrySetOutput(output); } else { var output = await((Task <T>)result).ConfigureAwait(false); computed.TrySetOutput(output); } } catch (OperationCanceledException) { throw; } catch (Exception e) { computed.TrySetOutput(Result.Error <T>(e)); // Weird case: if the output is already set, all we can // is to ignore the exception we've just caught; // throwing it further will probably make it just worse, // since the the caller have to take this scenario into acc. } return(computed); }
protected override async ValueTask <IComputed <T> > ComputeAsync( InterceptedInput input, IComputed <T>?cached, CancellationToken cancellationToken) { var tag = LTagGenerator.Next(); var method = Method; var output = new Computed <InterceptedInput, T>(method.Options, input, tag); try { using var _ = Computed.ChangeCurrent(output); var resultTask = input.InvokeOriginalFunction(cancellationToken); if (method.ReturnsComputed) { if (method.ReturnsValueTask) { var task = (ValueTask <IComputed <T> >)resultTask; await task.ConfigureAwait(false); // output == task.Result here, so no need to call output.TrySetOutput(...) } else { var task = (Task <IComputed <T> >)resultTask; await task.ConfigureAwait(false); // output == task.Result here, so no need to call output.TrySetOutput(...) } } else { if (method.ReturnsValueTask) { var task = (ValueTask <T>)resultTask; var value = await task.ConfigureAwait(false); output.TrySetOutput(value !); } else { var task = (Task <T>)resultTask; var value = await task.ConfigureAwait(false); output.TrySetOutput(value !); } } } catch (OperationCanceledException) { throw; } catch (Exception e) { output.TrySetOutput(Result.Error <T>(e)); // Weird case: if the output is already set, all we can // is to ignore the exception we've just caught; // throwing it further will probably make it just worse, // since the the caller have to take this scenario into acc. } return(output); }