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

时间:2017-05-07 19:39:07

标签: c# akka.net

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

我有一个自定义时间源similliar到NodaTime FakeClock类。

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

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

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

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

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.
}

在事件上发送消息时使用的模式是什么?有没有?

1 个答案:

答案 0 :(得分:2)

您的问题的来源可能是在SelfTimer_TimerTicked成员来电。原因是Self就像Context一样是计算属性,只能在当前正在执行的actor的线程中使用。如果你从外部调用它(另一个线程就像定时器回调一样),它可能没有被初始化。

弱解决方案只是在其他某个字段中存储对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();
    }
}