Startsidan  ▸  Texter  ▸  Teknikblogg

Anders Hesselbom

Programmerare, skeptiker, sekulärhumanist, antirasist.
Författare till bok om C64 och senbliven lantis.
Röstar pirat.

Schemalagda meddelanden i Akka .NET

2015-05-20

Denna gång tänker jag använda en Windows Forms Application för att visa schemaläggaren i Akka .NET. Som vanligt, för att komma åt Akka .NET i ditt projekt, växla till fönstret Package Manager Console och skriv Install-Package Akka. Om du inte ser Package Manager Console, klicka på rullgardinsmenyn Tools, välj Library Package Manager och Package Manager Console.

Programmet består av följande meddelandeklass:

public class TimedMessage
{
   public string Message { get; private set; }
   public TimedMessage(string message)
   {
      this.Message = message;
   }
}

…och följande aktör:

public class Listen : ReceiveActor
{
   public Listen()
   {
      this.Receive<TimedMessage>(x =>
      {
         System.Diagnostics.Debug.WriteLine(x.Message);
      });
   }
}

Huvudfönstret har läst in namnrymden Akka.Actor för att några extension methods ska vara tillgängliga…

using Akka.Actor;

…och innehåller en knapp som heter button1. I formulärets Load-event skapas aktörssystemet och aktören och under knappen så skickar jag ett meddelande (TimedMessage) till aktören.

public partial class Form1 : Form
{
   private ActorSystem actorSystem;
   private IActorRef listen;

   public Form1()
   {
      InitializeComponent();
   }

   private void button1_Click(object sender, EventArgs e)
   {
      this.listen.Tell(new TimedMessage("Helloooo!"));
   }

   private void Form1_Load(object sender, EventArgs e)
   {
      this.actorSystem = ActorSystem.Create("ActorSystem");
      this.listen = this.actorSystem.ActorOf(
         Props.Create(typeof(Listen)));
   }
}

Om du testar detta lilla exempel så märker du att meddelandet går iväg till aktören i samma ögonblick som du klickar på knappen. Men istället för att anropa aktörens Tell-funktion i Click-eventet, så kan vi använda aktörssystemets Scheduler-property. Den har ett antal funktioner för schemaläggning och upprepning. Följande förändring gör att meddelandet går iväg först tre sekunder efter att man klickar på knappen.

private void button1_Click(object sender, EventArgs e)
{
   this.actorSystem.Scheduler.ScheduleTellOnce(
      TimeSpan.FromSeconds(3), this.listen,
      new TimedMessage("Helloooo!"), ActorRefs.Nobody);
}

Funktionen ScheduleTellOnce schemalägger ett meddelande istället för att skicka iväg det direkt. Det är det första argumentet som bestämmer när meddelandet ska gå iväg. Uttrycket TimeSpan.FromSeconds(3) säger att meddelandet ska gå iväg efter tre sekunder, oavsett vad klockan är. Schemaläggaren förväntar sig att man anger relativa tider, så om jag vill att meddelandet ska gå iväg ett bestämt klockslag, t.ex. den 19/5 kl. 13:30, kan jag istället skriva new DateTime(2015, 5, 19, 13, 30, 0).Subtract(DateTime.Now).

Det andra argumentet är aktören som ta emot meddelandet. I mitt exempel finns endast en aktör, så den skickar jag in. Det tredje argumentet är meddelandet som ska skickas. Slutligen, det fjärde argumentet är avsändaren. Om det är en aktör som skickar meddelandet, skriver man normalt this.Self, men det går bra att skicka in en annan aktör här.

I mitt fall när det inte finns någon aktör som avsändare (det är ju formuläret som skickar) så kan det vara frestande att skicka in null, men i dagsläget fungerar inte det. Klassen ActorRefs innehåller konstanter som kan användas som substitut för en avsändare, och Nobody betyder just ingen. (Detta kan komma att ändras.)

Men tänk dig att du vill bli informerad när något inte händer. Från första klicket vill du veta om användaren fortsätter att klicka var tredje sekund, eller om användaren har blivit passiv. Det kan vi lösa på följande vis:

1. När första klicket inträffar, säger vi att vi vill ha ett meddelande om tre sekunder.

2. När knappen blir klickad på nästa gång, inom tre sekunder, så avbryter vi beställningen, och gör om den på nytt.

3. Skulle användaren inte klicka inom tre sekunder så går meddelandet iväg eftersom det inte hunnit avbrytas. Således vet vi att användaren har blivit passiv.

Detta kräver minimala förändringar. Först vill vi ha ett kvitto på beställningen. För detta använder jag en medlemsvariabel av typen Akka.Actor.ICancelable.

private ICancelable idle_detector = null;

Funktionen ScheduleTellOnce ger ingen retur, men ScheduleTellOnceCancelable ger ett svar i ICancelable-format som jag kan lagra i min nya medlemsvariabel. När användaren klickar, kan jag kolla om det finns en liggande beställning, och i så fall kan jag avbryta den – eftersom användaren klickat så är han ju inte inaktiv.

private void button1_Click(object sender, EventArgs e)
{
   if (!(this.idle_detector == null))
      this.idle_detector.Cancel();
   this.idle_detector =
      this.actorSystem.Scheduler.ScheduleTellOnceCancelable(
      TimeSpan.FromSeconds(3), this.listen,
      new TimedMessage("Idle!!!"), ActorRefs.Nobody);
}

För att testa programmet, starta och klicka lite då och då på knappen. För varje gång tre sekunder får passera utan något klick så går meddelandet iväg till aktören.

Categories: C#

Tags: Akka .NET

Leave a Reply

Your email address will not be published. Required fields are marked *



En kopp kaffe!

Bjud mig på en kopp kaffe (20:-) som tack för bra innehåll!

Bjud på en kopp kaffe!

Om...

Kontaktuppgifter, med mera, finns här.

Följ mig

Twitter Instagram
GitHub RSS

Public Service

Folkbildning om public service.

Hem   |   linktr.ee/hesselbom   |   winsoft.se   |   80tal.se   |   Filmtips