The Top 7 Mistakes Newbies Make with Akka.NET解释了为什么在actor中使用async / await通常是一个坏主意:


  [...]我们看到最终用户在单个消息处理程序中开发了许多嵌套的异步/等待操作。大多数用户都忽略了这样做的代价:在每次等待操作之间,actor无法处理任何其他消息,因为这些等待仍然是原始消息的“一次1条消息”保证的一部分!


但是在Petabridge Akka .NET Bootcamp的Unit 3 Lesson 4中,此示例被认为是可以的:

// asynchronously download the image and pipe the results to ourself
_httpClient.GetAsync(imageUrl).ContinueWith(httpRequest =>
{
    var response = httpRequest.Result;

    // successful img download
    if (response.StatusCode == HttpStatusCode.OK)
    {
        var contentStream = response.Content.ReadAsStreamAsync();
        try
        {
            contentStream.Wait(TimeSpan.FromSeconds(1));
            return new ImageDownloadResult(image,
                response.StatusCode, contentStream.Result);
        }
        catch //timeout exceptions!
        {
            return new ImageDownloadResult(image, HttpStatusCode.PartialContent);
        }
    }

    return new ImageDownloadResult(image, response.StatusCode);
},
  TaskContinuationOptions.ExecuteSynchronously)
 .PipeTo(Self);


以我的理解,演员在完成GetAsync()ContinueWith()之前将无法处理任何其他消息,这正是PipeTo()试图避免的问题。

我在这里想念什么吗?

最佳答案

TaskContinuationOptions.ExecuteSynchronously表示ContinueWith将与将任务转换为完成的代码(TaskContinuationOptions)同步运行。

示例中的代码将触发任务,设置ContinueWith()PipeTo(),然后返回。 actor可以自由接收新消息,并且当任务完成时,PipeTo()将向其发送结果消息。

正如Gigi提到的,​​如果要在演员中等待任务,那么它将被阻止。

可能会认为ContinueWith()也返回任务,而这正是PipeTo()对其进行操作的原因。

这是Akka.net Github中的PipeTo扩展:

    public static Task PipeTo<T>(this Task<T> taskToPipe, ICanTell recipient, IActorRef sender = null, Func<T, object> success = null, Func<Exception, object> failure = null)
    {
        sender = sender ?? ActorRefs.NoSender;
        return taskToPipe.ContinueWith(tresult =>
        {
            if (tresult.IsCanceled || tresult.IsFaulted)
                recipient.Tell(failure != null
                    ? failure(tresult.Exception)
                    : new Status.Failure(tresult.Exception), sender);
            else if (tresult.IsCompleted)
                recipient.Tell(success != null
                    ? success(tresult.Result)
                    : tresult.Result, sender);
        }, CancellationToken.None, TaskContinuationOptions.ExecuteSynchronously, TaskScheduler.Default);
    }

关于c# - Akka .NET PipeTo()与ContinueWith(),我们在Stack Overflow上找到一个类似的问题:https://stackoverflow.com/questions/38813533/

10-09 03:15