2017-05-07 128 views
1

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

我有一个自定义时间源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

你能否提供一些简单的片断? – Horusiath

+0

完成。这是否提供了足够的细节? –

回答

1

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

弱解决方案是将Self的引用存储在某个其他字段中,并使用该字段来发送消息。你的情况

更好的解决方案是使用内置Akka.NET调度,提供在指定的时间间隔执行操作或拨打电话的能力:

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(); 
    } 
} 
+0

我很乐意使用Scheduler,但它使用实时时钟,对不对?它甚至可以替换为我自己的实现? –

+1

出于测试目的(Akka.TestKit),有一个实现虚拟时间的实现:基本上可以调用Scheduler.Advance来按指定的时间前进。 – Horusiath

+0

我正在写一个模拟器,其中时间控件是应用程序的一部分。 –

相关问题