如何在 akka.net 的事件处理程序中发送消息?

Jan*_*kun 1 c# akka.net

我有一个演员,它有一个自定义计时器,可以以非实时间隔触发事件。(这就是为什么我不能使用调度程序)在事件处理程序中,我想向自己或另一个参与者发送消息。我收到 NotSupportedException。

我有一个类似于 NodaTime FakeClock 类的自定义时间源。

public class NodaTimeControllableClock
{
    public void AddInterval(Duration interval);
    public Instant Now { get; protected set; }
    public event EventHandler<TimeChangedEventArgs<Duration>> TimeChanged;
}     
Run Code Online (Sandbox Code Playgroud)

它在计时器类中用于每隔指定的时间触发事件。

public class NodaTimer
{
    Duration Interval { get; set; }
    void Start();
    void Stop();
    bool IsRunning { get; private set; }
    event EventHandler<TimerTickedEventArgs> TimerTicked;
}
Run Code Online (Sandbox Code Playgroud)

现在,我为一些演员创建一个计时器实例并将其存储在其中。

protected override void PreStart()
{
    base.PreStart();
    timer.Interval = Duration.FromSeconds(1);
    timer.TimerTicked += Timer_TimerTicked; 
    timer.Start();
}

private void Timer_TimerTicked(object sender, TimerTickedEventArgs e)
{
    Self.Tell(new SomeMessage());
    //Here I want to send the message to the parent or 
    //if it's impossible to do so I could queue some message
    //to the Self messagebox.
}
Run Code Online (Sandbox Code Playgroud)

发送事件消息的模式是什么?有没有?

Bar*_*ski 5

您的问题的根源可能是Self内部拨打的会员电话Timer_TimerTicked。这样做的原因是Self就像Context是一个计算属性,它仅在当前执行的参与者的线程中可用。如果您从外部调用它(另一个线程,如计时器回调的情况),它可能未初始化。

弱解决方案只是存储对Self在其他字段中,并使用该字段来发送消息。

对于您的情况,更好的解决方案是使用内置的 Akka.NET Scheduler,它提供了在指定的时间间隔内执行操作或进行调用的能力:

class MyActor : ReceiveActor
{
    private readonly ICancelable cancelTimer;

    public MyActor()
    {
        var interval = TimeSpan.FromSeconds(1);
        cancelTimer = Context.System.Scheduler
            .ScheduleTellRepeatedlyCancelable(interval, interval, Self, new SomeMessage(), ActorRefs.NoSender);
    }

    protected override void PostStop()
    {
        cancelTimer.Cancel();
        base.PostStop();
    }
}
Run Code Online (Sandbox Code Playgroud)