I know PipeTo , but some things, like synchronous waiting on a nested continuation, seem to go against an asynchronous and waiting path.
So, my first question [1] would be: is there any βmagicβ here, so that we can just synchronously wait for the nested tasks to continue, and still async at the end?
While we are in async state and expect differences, how are errors handled?
Let me create a simple example:
public static class AsyncOperations { public async static Task<int> CalculateAnswerAsync() { await Task.Delay(1000).ConfigureAwait(false); throw new InvalidOperationException("Testing!");
In a "regular", asynchronous and pending way:
var answer = await AsyncOperations.CalculateAnswerAsync(); var converted = await AsyncOperations.ConvertAsync(answer);
the exception will exit the first operation, as expected.
Now create an actor that will work with these asynchronous operations. For the argument, suppose that CalculateAnswerAsync and ConvertAsync should be used one after the other as one complete operation (similarly, for example, StreamWriter.WriteLineAsync and StreamWriter.FlushAsync if you just want to write one line to the stream).
public sealed class AsyncTestActor : ReceiveActor { public sealed class Start { } public sealed class OperationResult { private readonly string message; public OperationResult(string message) { this.message = message; } public string Message { get { return message; } } } public AsyncTestActor() { Receive<Start>(msg => { AsyncOperations.CalculateAnswerAsync() .ContinueWith(result => { var number = result.Result; var conversionTask = AsyncOperations.ConvertAsync(number); conversionTask.Wait(1500); return new OperationResult(conversionTask.Result); }) .PipeTo(Self); }); Receive<OperationResult>(msg => Console.WriteLine("Got " + msg.Message)); } }
If there are no exceptions, I still get Got 42 :) without any problems, which brings me back to the "magic" point above [1]. In addition, do the AttachedToParent and ExecuteSynchronously flags ExecuteSynchronously , which are optional in the example, or are they largely necessary for everything to work as intended? They don't seem to affect exception handling ...
Now, if CalculateAnswerAsync throws an exception, which means result.Result throws AggregateException , it almost swallowed without a trace.
What should I do, if at all possible, to make an exception inside an asynchronous operation, failing the actor as a "regular" exception?