Skocz do zawartości

Akka.net – pierwszy przykład


DevStart Blogi

Recommended Posts

W ostatnich dwóch wpisach pokazałem zasady działania modelu aktor. W kolejnych postach będę korzystał już z Akka.net zamiast pseudokodu. Dzisiaj czysty opis podstaw API – bez konkretnego problemu do rozwiązania.

Akka.net można zainstalować w formie pakietu Nuget:

Install-Package Akka

Następnie definiujemy wiadomość za pomocą zwyklej klasy typu immutable:

    public class TransferMoney
    {
        public string From { get; private set; }
        public string To { get; private set; }

        public TransferMoney(string from,string to)
        {
            From = @from;
            To = to;
        }
    }

Każdy aktor powinien dziedziczyć np. po ReceiveActor:

    public class TransferMoneyActor : ReceiveActor
    {
        public TransferMoneyActor()
        {
            Receive<TransferMoney>(msg =>
            Console.WriteLine("Transferring money from {0} to {1}", msg.From, msg.To));
        }
    }

Za pomocą Receive definiujemy, jakie wiadomości chcemy obsługiwać. Powyższa klasa zatem będzie odbierać wiadomości typu TransferMoney.
W akka.net aktorzy egzystują w tzw. ActorSystem. Aktorzy z dwóch różnych systemów są od siebie odizolowani. Inicjacja nowego systemu jest prosta:

var system = ActorSystem.Create("JakasNazwa");

Jak wiemy, aktorzy należą do konkretnych systemów, zatem w celu stworzenia aktora należy:

var actor1 = system.ActorOf<TransferMoneyActor>();

Wysłanie wiadomości odbywa się za pomocą metody Tell. Całość wygląda więc następująco:

var system = ActorSystem.Create("JakasNazwa");

var actor1 = system.ActorOf<TransferMoneyActor>();

actor1.Tell(new TransferMoney("nadawca", "odbiorca"));

Z poprzednich wpisów pamiętamy, że wiadomości są kolejkowane i wykonywane asynchronicznie. Stwórzmy zatem następującego aktora:

   public class TransferMoneyActor : ReceiveActor
    {
        public TransferMoneyActor()
        {
            Receive<TransferMoney>(DoWork,shouldHandle:null);
        }

        private void DoWork(TransferMoney msg)
        {
            Console.WriteLine("{0}:{1}",DateTime.Now,Thread.CurrentThread.ManagedThreadId);

            Thread.Sleep(5000);
        }
    }

Jeśli faktycznie wiadomości są kolejkowane i wykonywane jedno po drugim, wtedy powinniśmy zawsze widzieć ten sam identyfikator wątku w odstępach dokładnie 5 sekund. W celu udowodnienia, że zadania są wykonywane asynchronicznie, w pętli wyślemy 10 wiadomości:

            for (int i = 0; i < 10; i++)
            {
                Console.WriteLine("{0}: Wysylanie wiadomosci nr {1}", DateTime.Now,i);
                actor1.Tell(new TransferMoney("nadawca", "odbiorca"));
            }

Jeśli są synchronicznie wykonywane, wtedy po wyświetleniu tekstu “Wysylanie wiadomosci nr…”, powinniśmy zobaczyć numer wątku. Jeśli z kolei wykonywane są asynchronicznie, tak jak tego spodziewamy się, wtedy metoda Tell powinna wyłącznie umieścić wiadomość w kolejce.

Screenshot potwierdzający założenia:

tasks

W następnym wpisie, zajmiemy się znów jakimś problemem wielowątkowym, który najpierw rozwiążemy w “klasyczny sposób” z użyciem blokad, a później za pomocą modelu aktor.

Wyświetl pełny artykuł

Link do komentarza
Udostępnij na innych stronach

Join the conversation

You can post now and register later. If you have an account, sign in now to post with your account.

Gość
Odpowiedz...

×   Wkleiłeś zawartość bez formatowania.   Usuń formatowanie

  Only 75 emoji are allowed.

×   Your link has been automatically embedded.   Display as a link instead

×   Your previous content has been restored.   Clear editor

×   You cannot paste images directly. Upload or insert images from URL.

×
×
  • Utwórz nowe...