Я создаю порт для рамки AKKA для .NET(не считайте это слишком серьезным сейчас, это выходная часть части Актера прямо сейчас)
У меня возникают проблемы с поддержкой "Будущее". В Java/Scala Akka фьючерсы ожидаются синхронно с вызовом Await. Как и .NET Task.Wait()
Моя цель - поддерживать true async. Он работает прямо сейчас, но продолжение выполняется в неправильном потоке в моем текущем решении.
Это результат передачи сообщения одному из моих участников, которые содержат блок ожидания для будущего. Как вы можете видеть, актер всегда выполняется в одном потоке, а блок ожидания выполняется на случайном потоке threadpool.
actor thread: 6
await thread 10
actor thread: 6
await thread 12
actor thread: 6
actor thread: 6
await thread 13
...
Актер получает сообщение с использованием DataFlow BufferBlock<Message>
Вернее, я использую RX над буферным блоком для подписки на сообщения.
Он настроен следующим образом:
var messages = new BufferBlock<Message>()
{
BoundedCapacity = 100,
TaskScheduler = TaskScheduler.Default,
};
messages.AsObservable().Subscribe(this);
Пока все хорошо.
Однако, когда я жду будущий результат. так:
protected override void OnReceive(IMessage message)
{
....
var result = await Ask(logger, m);
// This is not executed on the same thread as the above code
result.Match()
.With<SomeMessage>(t => {
Console.WriteLine("await thread {0}",
System.Threading.Thread.CurrentThread.GetHashCode());
})
.Default(_ => Console.WriteLine("Unknown message"));
...
Я знаю, что это обычное поведение async ждет, но я действительно должен убедиться, что только один поток имеет доступ к моему игроку.
Я не хочу, чтобы будущее выполнялось синхронно, я хочу запустить async так же, как обычно, но я хочу, чтобы продолжение выполнялось в том же потоке, что и процессор/актер.
Мой код для будущей поддержки выглядит следующим образом:
public Task<IMessage> Ask(ActorRef actor, IMessage message)
{
TaskCompletionSource<IMessage> result =
new TaskCompletionSource<IMessage>();
var future = Context.ActorOf<FutureActor>(name : Guid.NewGuid().ToString());
// once this object gets a response,
// we set the result for the task completion source
var futureActorRef = new FutureActorRef(result);
future.Tell(new SetRespondTo(), futureActorRef);
actor.Tell(message, future);
return result.Task;
}
Любые идеи, что я могу сделать, чтобы заставить продолжение работать в том же потоке, который запустил вышеуказанный код?