Асинхронный вызов API внутри субъекта и исключения

Я знаю оPipeTo, нонекоторые вещи, такие как синхронное ожидание на вложенном продолжении, похоже, идут против асинхронного и ожидающего пути.

Итак, мой первый вопрос [1] будет таким: есть ли здесь какое-то «волшебство», чтобы мы могли просто синхронно ожидать вложенных задач в продолжении, а в конце оно все еще асинхронно?

Пока мы находимся в асинхронном режиме и ждем различий, как обрабатываются сбои?

Давайте создадим простой пример:

public static class AsyncOperations
{
    public async static Task<int> CalculateAnswerAsync()
    {
        await Task.Delay(1000).ConfigureAwait(false);
        throw new InvalidOperationException("Testing!");
        //return 42;
    }

    public async static Task<string> ConvertAsync(int number)
    {
        await Task.Delay(600).ConfigureAwait(false);
        return number + " :)";
    }
}

В «обычном», асинхронном и ожидающем способах:

var answer = await AsyncOperations.CalculateAnswerAsync();
var converted = await AsyncOperations.ConvertAsync(answer);

исключение будет всплывать после первой операции, как и следовало ожидать.

Теперь давайте создадим актера, который будет работать с этими асинхронными операциями. Ради аргумента, скажем, чтоCalculateAnswerAsync а такжеConvertAsync следует использовать один за другим как одну полную операцию (аналогично, например,StreamWriter.WriteLineAsync а такжеStreamWriter.FlushAsync если вы просто хотите написать одну строку в поток).

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

Если нет никаких исключений, я все еще получаюGot 42 :) без каких-либо проблем, что возвращает меня к «волшебному» пункту выше [1]. Кроме того, являютсяAttachedToParent а такжеExecuteSynchronously флаги, представленные в примере, необязательны, или они в значительной степени необходимы, чтобы все работало как задумано? Похоже, они не влияют на обработку исключений ...

Теперь, еслиCalculateAnswerAsync выдает исключение, что означает, чтоresult.Result бросаетAggregateExceptionГлухо проглочено без следа.

Что я должен сделать здесь, если это возможно, чтобы исключение внутри асинхронной операции приводило к аварийному завершению действия актера, как и в случае «обычного» исключения?

Ответы на вопрос(2)

Ваш ответ на вопрос