为什么我应该使用PipeTo()使用Sender闭包?

ale*_*xey 5 c# akka akka.net

这是在Akka.NET 中使用的官方示例PipeTo():

Receive<BeginProcessFeed>(feed =>
{
    //instance variable for closure
    var senderClosure = Sender; 
    SendMessage(string.Format("Downloading {0} for RSS/ATOM processing...", feed.FeedUri));

    //reply back to the sender
    _feedFactory.CreateFeedAsync(feed.FeedUri).PipeTo(senderClosure);
});
Run Code Online (Sandbox Code Playgroud)

问题是我们为什么要Sender在这里使用闭包?为什么不使用:

_feedFactory.CreateFeedAsync(feed.FeedUri).PipeTo(Sender);
Run Code Online (Sandbox Code Playgroud)

在此示例和文档中,它表示必须在此处使用闭包.但我认为没有任何理由这样做.

如果我们使用ContinueWith()它是合理的,在continuation中使用闭包,但不作为PipeTo()参数.

我错过了什么吗?

And*_*ewS 5

这里要理解两件事:

  1. Sender不是静态属性.Sender实际上是一个函数,IActorContext它返回正在处理的当前消息的发送者.每次上下文从邮箱获取新邮件时,返回的值都会更改.

  2. PipeTo是一个延续,当在线程池上执行该延续时,调用Sender将访问IActorContext启动任务的完全相同的对象.无法保证Sender上下文中的当前流是相同的,因为自从任务开始以来将新消息推送到actor中进行处理.

所以我们缓存Sender局部变量的值,以保证我们在执行时都瞄准PipeTo正确IActorRef.

  • 发件人是一种上下文敏感的方法 - 每次演员收到一条消息时,它的值都会发生变化.如果Sender的当前值没有缓存在本地变量中,当你使用PipeTo时它会被关闭,那么你的Sender调用很可能会返回一个与你预期的actor不同的值.我们已经能够多次复制这个错误:p (3认同)