I know about PipeTo, but some stuff, like synchronous waiting on nested continuation, seems to go against the async & await way.
So, my first question [1] would be:
The joys of error-handling in the TPL :)
Task
inside of an actor, that task runs independently on the ThreadPool
from your actor. This means that anything you do inside that Task
will already be asynchronous from your actor - because it's running on a different thread. This is why I made a Task.Wait call inside the PipeTo sample you linked to at the top of your post. Makes no difference to the actor - it just looks like a long-running task.conversionTask.Result
property will throw the exception captured during its run, so you'll want to add some error-handling inside your Task
to ensure that your actor gets notified that something went wrong. Notice I did just that here: https://github.com/petabridge/akkadotnet-code-samples/blob/master/PipeTo/src/PipeTo.App/Actors/HttpDownloaderActor.cs#L117 - if you turn your Exceptions into messages your actor can handle: birds start singing, rainbows shine, and TPL errors stop being a source of pain and agony.Now, if the CalculateAnswerAsync throws an exception, which means that result.Result throws AggregateException, it's pretty much swallowed without a trace.
The AggregateException
will contain the list of inner exceptions wrapped inside of it - the reason the TPL has this concept of aggregate errors is in the event that (a) you have one task that is the continuation of multiple tasks in aggregate, i.e. Task.WhenAll
or (b) you have errors propagated up the ContinueWith
chain back to the parent. You can also call the AggregateException.Flatten()
call to make it a little easier to manage nested exceptions.
Dealing with Exceptions from the TPL is a nuisance, that's true - but the best way to deal with it is to try..catch..
exceptions inside your Task
and turn them into message classes your actor can handle.
Also, are the AttachedToParent and ExecuteSynchronously flags provided in an example optional, or are they pretty much required to have everything working as intended?
This is mostly an issue for when you have continuations on continuations - PipeTo
automatically uses these flags on itself. It has zero impact on error handling, but ensures that your continuations are executed immediately on the same thread as the original Task
.
I recommend using these flags only when you're doing a lot of nested continuations - the TPL starts to take some liberties with how it schedules your tasks once you go deeper than 1 continuation (and in fact, flags like OnlyOnCompleted stop being accepted after more than 1 continuation.)