Reliable Actors 可重入性Reliable Actors reentrancy

默认情况下,Reliable Actors 运行时允许基于逻辑调用上下文的可重入性。The Reliable Actors runtime, by default, allows logical call context-based reentrancy. 因此执行组件在处于相同调用上下文链中时,可进行重入操作。This allows for actors to be reentrant if they are in the same call context chain. 例如,如果执行组件 A 将消息发送给执行组件 B,而后者将消息发送给执行组件 C。在处理消息的过程中,如果执行组件 C 调用执行组件 A,这样的消息重入是允许的。For example, Actor A sends a message to Actor B, who sends a message to Actor C. As part of the message processing, if Actor C calls Actor A, the message is reentrant, so it will be allowed. 如果消息属于不同调用上下文,则会在执行组件 A 处受阻,直到处理完现有消息为止。Any other messages that are part of a different call context will be blocked on Actor A until it finishes processing.

执行组件重入有两个相关选项,可在 ActorReentrancyMode 枚举中定义:There are two options available for actor reentrancy defined in the ActorReentrancyMode enum:

  • LogicalCallContext(默认行为)LogicalCallContext (default behavior)
  • Disallowed - 禁用重入Disallowed - disables reentrancy
public enum ActorReentrancyMode
{
    LogicalCallContext = 1,
    Disallowed = 2
}
public enum ActorReentrancyMode
{
    LogicalCallContext(1),
    Disallowed(2)
}

注册期间,可在 ActorService的设置中配置可重入性。Reentrancy can be configured in an ActorService's settings during registration. 该设置适用于执行组件服务中创建的所有执行组件实例。The setting applies to all actor instances created in the actor service.

以下示例演示了将重入模式设置为 ActorReentrancyMode.Disallowed 的执行组件服务。The following example shows an actor service that sets the reentrancy mode to ActorReentrancyMode.Disallowed. 在这种情况下,如果执行组件向另一个执行组件发送可重入消息,则会引发类型为 FabricException 的异常。In this case, if an actor sends a reentrant message to another actor, an exception of type FabricException will be thrown.

static class Program
{
    static void Main()
    {
        try
        {
            ActorRuntime.RegisterActorAsync<Actor1>(
                (context, actorType) => new ActorService(
                    context,
                    actorType, () => new Actor1(),
                    settings: new ActorServiceSettings()
                    {
                        ActorConcurrencySettings = new ActorConcurrencySettings()
                        {
                            ReentrancyMode = ActorReentrancyMode.Disallowed
                        }
                    }))
                .GetAwaiter().GetResult();

            Thread.Sleep(Timeout.Infinite);
        }
        catch (Exception e)
        {
            ActorEventSource.Current.ActorHostInitializationFailed(e.ToString());
            throw;
        }
    }
}
static class Program
{
    static void Main()
    {
        try
        {
            ActorConcurrencySettings actorConcurrencySettings = new ActorConcurrencySettings();
            actorConcurrencySettings.setReentrancyMode(ActorReentrancyMode.Disallowed);

            ActorServiceSettings actorServiceSettings = new ActorServiceSettings();
            actorServiceSettings.setActorConcurrencySettings(actorConcurrencySettings);

            ActorRuntime.registerActorAsync(
                Actor1.getClass(),
                (context, actorType) -> new FabricActorService(
                    context,
                    actorType, () -> new Actor1(),
                    null,
                    stateProvider,
                    actorServiceSettings, timeout);

            Thread.sleep(Long.MAX_VALUE);
        }
        catch (Exception e)
        {
            throw e;
        }
    }
}

后续步骤Next steps