使用ContinueWith()的Akka .NET PipeTo()

问题描述 投票:2回答:2

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

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

然而在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()试图避免的问题。

我在这里错过了什么吗?

c# asynchronous akka.net
2个回答
2
投票

TaskContinuationOptions.ExecuteSynchronously意味着ContinueWith将与转换任务完成的代码(TaskContinuationOptions)同步运行。

示例中的代码将触发任务,设置ContinueWith()PipeTo(),然后返回。演员可以自由地接收新消息,当任务完成时,PipeTo()会将结果消息发送给它。

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

可能有助于认为ContinueWith()也会返回一项任务,这就是PipeTo()的运作方式。

这是qazxsw poi中的PipeTo扩展:

Akka.net Github

1
投票

我认为正在发生的事情是,由于没有等待 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); } ,整个事情会异步发射并且不会阻止执行。

虽然发生了这一切,但演员可以自由处理其他消息。

© www.soinside.com 2019 - 2024. All rights reserved.