C# Akka.net synchronus是否正在处理消息,而不是在事件处理程序中等待?

C# Akka.net synchronus是否正在处理消息,而不是在事件处理程序中等待?,c#,multithreading,asynchronous,async-await,akka.net,C#,Multithreading,Asynchronous,Async Await,Akka.net,我对akka.net的理解是,一封邮件从邮箱一次处理一封,而对于给定的参与者,它不会一次处理多封邮件 就使用await关键字而言,这意味着什么?我认为它不会在演员模式世界中增加任何价值 我知道akka.net解决了多线程问题,允许您创建分布式系统 ReceiveAsync事件处理程序,使用它们的目的是什么?是否需要在actor中使用wait和async方法。Akka actor模型允许您将异步工作流表示为状态机。类似地,C#编译器构建负责处理异步/等待代码的代码。所以,是的,您可以在Akka.N

我对akka.net的理解是,一封邮件从邮箱一次处理一封,而对于给定的参与者,它不会一次处理多封邮件

就使用await关键字而言,这意味着什么?我认为它不会在演员模式世界中增加任何价值

我知道akka.net解决了多线程问题,允许您创建分布式系统


ReceiveAsync事件处理程序,使用它们的目的是什么?是否需要在actor中使用wait和async方法。

Akka actor模型允许您将异步工作流表示为状态机。类似地,C#编译器构建负责处理异步/等待代码的代码。所以,是的,您可以在Akka.NET中构建一个完全异步的代码,而不必使用async/await——大多数Akka.NET内部都是这样工作的。关于
ReceiveAsync
,有几点需要记住,其中最大的一点是关于可重入性

可重入 我将在这里使用工作流的概念-您可以将工作流想象为一个多步骤流程,它实现某种请求:

  • 在基于消息的系统(如Akka,但也包括NServiceBus Sagas或Azure持久功能)中,工作流可以实现为一个状态机,它是不同触发器(消息)和处理块(消息处理程序)的组合
  • 在async/await中,可以将触发器表示为等待器,将处理块表示为一个等待调用和下一个等待调用之间的代码部分
  • 默认情况下,所有Akka参与者都是可重入的-这意味着,当您必须处理由许多步骤组成的工作流时(通常您可以通过使用
    Self.Tell(nextStepSignal)
    识别它们),它可以同时接受新的传入请求,这仅仅是因为启动新工作流的消息和已在进行的工作流的下一步的消息之间没有区别。因此,实际上,参与者能够执行许多并行工作流,同时仍然在单个线程上处理每个块

    虽然这在大多数情况下都是有用的属性,但有时您希望让参与者在处理工作流所需的整个时间内处于固定状态。当使用标准方法时,在Akka,这可以通过隐藏和成为/取消行为更改的组合来实现-我们更改参与者的行为并开始隐藏与该行为不相关的消息,一旦工作流完成,我们返回到以前的行为并取消等待消息的隐藏

    ReceiveAsync
    中的区别在于,它使参与者在异步消息处理程序完成之前不可重入。它是如何实现的?简单地说,在处理程序最终返回结果之前,actor的邮箱将被挂起。这意味着,在这段时间内,actor不会处理任何新消息。这有几个优点和缺点

    优点:

    • 大多数情况下,它很容易与现有的.NET库一起使用。不是构建自己的状态机,而是让C#编译器生成自己的状态机
    • 您知道,任何其他并行执行的工作流都不会改变参与者的状态
    • 你不需要把东西藏起来。这在与其他功能(如SmallestMailbox router option)结合使用时有时很有用:因为隐藏实际上是从参与者的邮箱中拾取元素,所以即使不处理它们,它也会收到越来越多的消息(如具有最小邮箱的消息)
    • 对于某些调试情况,可以获得清晰的堆栈跟踪
    缺点:

    • 由于actor无法处理其他请求,因此它与其他actor的通信能力有限。也就是说,您仍然可以对其他参与者使用
      Ask
      ,但这比基于
      Tell
      的消息交换更昂贵
    • 一般来说,Akka参与者被优化以利用其可重入性模型,使用
      ReceiveAsync
      被认为是较慢的选择。但是,您需要制定自己的措施,以确定您满意的速度
    • 由于actor是不可重入的,所以在当前工作流完成之前,它不会处理新消息。这意味着actor可能不会处理任何新消息,因为它正在等待超时(或者如果您没有指定任何超时,则永远等待)
    • 在调试有状态组件(如actor)时,手动定制的状态机可能会告诉您超过一英里长的堆栈跟踪:这仅仅是因为堆栈跟踪并没有说明崩溃组件的实际状态