2015-10-28 1 views
7

Это обычный сценарий, с которым я сталкиваюсь, где у меня есть два (или более) субъекта, которые получают некоторые данные асинхронно, а затем мне нужно выполнить операцию, когда все будет готово.Akka.net ждет несколько фрагментов данных

Каков общий шаблон для этого?

Вот упрощенный пример.

public MasterActor : ReceiveActor 
{ 
    public MasterActor() 
    { 
      Initialize(); 
    } 

    public void Initiaize() 
    { 
     Receive<DoSomeWork>(_ => 
     { 
       var actor1 = Context.ActorOf(Props.Create(() => new Actor1()); 
       var actor2 = Context.ActorOf(Props.Create(() => new Actor2()); 

       // pretend these actors send responses to their senders 
       // for sake of example each of these methods take between 1 and 3 seconds 
       actor1.Tell(new GetActor1Data()); 
       actor2.Tell(new GetActor2Data()); 
     }); 

     Receive<Actor1Response>(m => 
     { 
      //actor 1 has finished it's work 
     }); 

     Receive<Actor2Response>(m => 
     { 
      //actor 2 has finished it's work 
     }); 
    } 
} 

Чтобы начать это у меня отправить на DoSomeWork сообщение MasterActor.

Каков общий способ выполнения операции, когда у меня есть как Actor1Response, так и Actor2Response.

Я действительно не хочу иметь логику в каждом обработчике приема, проверяя, завершен ли другой или что-то в этом роде. Я думаю, что я думаю о чем-то подобном методу Task.WaitAll().

Я просто атакую ​​проблему не так? Нужно ли мне переписывать актеров по-другому?

Любые общие шаблоны или решения были бы удивительными.

ответ

3

Общим решением для этого является привязка какого-либо идентификатора корреляции, разделяемого как сообщениями запроса, так и ответами - так как актор обрабатывает сообщения синхронно, это может быть снято с таймера int/long.

Вы просто сохраняете корреляционные идентификаторы в некоторой структуре данных (допустим, устанавливаете) внутри вызывающего абонента, а когда ответ получен, удалите его идентификатор корреляции из набора. WaitAll заканчивается в основном, когда установлен пуст или происходит тайм-аут.

Вы можете установить таймаут с помощью Context.SetReceiveTimeout(timeout), таким образом, актер отправит метод ReceiveTimeout к себе после того, как он не получил какое-либо сообщение в течение некоторого времени.

Это поведение довольно общее и может быть абстрагировано довольно легко.

2

Простейшим способом сделать это было бы увеличение количества голосов на главном компьютере, когда каждый ребенок отвечает. Когда голова == подсчет детей, все готово.

Вы можете расширить это, чтобы считать только первое сообщение от каждого ребенка или конкретное сообщение от каждого ребенка, но все это сводится к подсчету в конце.

Смежные вопросы