❔ Akka.net Actors are not responding in time
I have a system that consists of two Actor classes and a class that calls these actors.
Actors:
2nd actor and problem follows in a second message, hang on
public class ActorsystemManager
{
readonly ActorSystem simulationActorSystem;
readonly IActorRef updateActorRef;
private List<ActorState> currentActorStates = new();
private readonly object locker = new();
public int ActorChangeInterval { get; set; }
// This property is accessed by both this class to write and by the interface to read. Always use "lock" when accessing it!
public List<ActorState> CurrentActorStates
{
get
{
lock (locker)
{
return currentActorStates;
}
}
set
{
lock (locker)
{
currentActorStates = value;
}
}
}
public ActorsystemManager(int actorChangeInterval, List<int[]> coordinates)
{
ActorChangeInterval = actorChangeInterval;
simulationActorSystem = ActorSystem.Create("SimulationActorSystem");
updateActorRef = simulationActorSystem.ActorOf(Props.Create<UpdateActor>(actorChangeInterval, coordinates), "UpdateActor");
UpdateTimer timer = new UpdateTimer();
timer.Elapsed += OnTimerTick;
}
private void OnTimerTick(object sender, EventArgs e)
{
updateActorRef.Ask<List<ActorState>>("update")
.ContinueWith(task =>
{
if (task.IsCompletedSuccessfully)
{
UpdateCurrentActorStates(task.Result);
}
// Handle other cases, like task.IsFaulted or task.IsCanceled, if needed
}, TaskScheduler.Default);
}
private void UpdateCurrentActorStates(List<ActorState> result)
{
CurrentActorStates = new List<ActorState>(result);
}
public void Trigger(int[] coordinates)
{
updateActorRef.Tell(coordinates);
}
public bool Dispose()
{
try
{
simulationActorSystem.Dispose();
return true;
}
catch (Exception)
{
return false;
}
}
}public class ActorsystemManager
{
readonly ActorSystem simulationActorSystem;
readonly IActorRef updateActorRef;
private List<ActorState> currentActorStates = new();
private readonly object locker = new();
public int ActorChangeInterval { get; set; }
// This property is accessed by both this class to write and by the interface to read. Always use "lock" when accessing it!
public List<ActorState> CurrentActorStates
{
get
{
lock (locker)
{
return currentActorStates;
}
}
set
{
lock (locker)
{
currentActorStates = value;
}
}
}
public ActorsystemManager(int actorChangeInterval, List<int[]> coordinates)
{
ActorChangeInterval = actorChangeInterval;
simulationActorSystem = ActorSystem.Create("SimulationActorSystem");
updateActorRef = simulationActorSystem.ActorOf(Props.Create<UpdateActor>(actorChangeInterval, coordinates), "UpdateActor");
UpdateTimer timer = new UpdateTimer();
timer.Elapsed += OnTimerTick;
}
private void OnTimerTick(object sender, EventArgs e)
{
updateActorRef.Ask<List<ActorState>>("update")
.ContinueWith(task =>
{
if (task.IsCompletedSuccessfully)
{
UpdateCurrentActorStates(task.Result);
}
// Handle other cases, like task.IsFaulted or task.IsCanceled, if needed
}, TaskScheduler.Default);
}
private void UpdateCurrentActorStates(List<ActorState> result)
{
CurrentActorStates = new List<ActorState>(result);
}
public void Trigger(int[] coordinates)
{
updateActorRef.Tell(coordinates);
}
public bool Dispose()
{
try
{
simulationActorSystem.Dispose();
return true;
}
catch (Exception)
{
return false;
}
}
}Actors:
internal class UpdateActor : ReceiveActor
{
public List<IActorRef> HexagonActors { get; set; }
public UpdateActor()
{
HexagonActors = new List<IActorRef>();
ReceiveAsync<string>(data => data.ToLower().Equals("update"), async data => await Update());
Receive<int[]>(data => Trigger(data));
}
public UpdateActor(int actorChangeInterval, List<int[]> coordinates) : this()
{
foreach (var item in coordinates)
{
string coordinatesText = $"{item[0]}_{item[1]}";
var child = Context.ActorOf(Props.Create<HexagonActor>(actorChangeInterval, item), coordinatesText);
HexagonActors.Add(child);
}
}
private async Task Update()
{
var actorStates = new List<ActorState>();
foreach (var actor in HexagonActors)
{
try
{
var actorState = await actor.Ask<ActorState>("update", TimeSpan.FromMilliseconds(200));
actorStates.Add(actorState);
}
catch (AskTimeoutException ex)
{
throw new AskTimeoutException("");
}
}
Sender.Tell(actorStates);
}
private void Trigger(int[] coordinates)
{
var coordinateAddress = $"{coordinates[0]}_{coordinates[1]}";
Context.ActorSelection("akka://SimulationActorSystem/user/UpdateActor/" + coordinateAddress).Tell("trigger");
}
}internal class UpdateActor : ReceiveActor
{
public List<IActorRef> HexagonActors { get; set; }
public UpdateActor()
{
HexagonActors = new List<IActorRef>();
ReceiveAsync<string>(data => data.ToLower().Equals("update"), async data => await Update());
Receive<int[]>(data => Trigger(data));
}
public UpdateActor(int actorChangeInterval, List<int[]> coordinates) : this()
{
foreach (var item in coordinates)
{
string coordinatesText = $"{item[0]}_{item[1]}";
var child = Context.ActorOf(Props.Create<HexagonActor>(actorChangeInterval, item), coordinatesText);
HexagonActors.Add(child);
}
}
private async Task Update()
{
var actorStates = new List<ActorState>();
foreach (var actor in HexagonActors)
{
try
{
var actorState = await actor.Ask<ActorState>("update", TimeSpan.FromMilliseconds(200));
actorStates.Add(actorState);
}
catch (AskTimeoutException ex)
{
throw new AskTimeoutException("");
}
}
Sender.Tell(actorStates);
}
private void Trigger(int[] coordinates)
{
var coordinateAddress = $"{coordinates[0]}_{coordinates[1]}";
Context.ActorSelection("akka://SimulationActorSystem/user/UpdateActor/" + coordinateAddress).Tell("trigger");
}
}2nd actor and problem follows in a second message, hang on