MailboxProcessor для симуляции врага может выглядеть так:
MailboxProcessor.Start(fun inbox ->
async {
while true do
let! message = inbox.Receive()
processMessage(message)
})
Он не потребляет поток, ожидая прибытия сообщения (строка let! message =
). Однако, как только сообщение прибудет, оно будет использовать поток (в пуле потоков). Если у вас есть 100 процессоров почтовых ящиков, которые все получают сообщение одновременно, они все будут пытаться проснуться и потреблять поток. Поскольку здесь обработка сообщений связана с ЦП, все сотни процессоров почтовых ящиков будут активированы и начнут порождать потоки (пул потоков). Это не очень хорошее представление.
Одной из ситуаций, в которой процессоры почтовых ящиков преуспевают, является ситуация, когда множество одновременно работающих клиентов отправляют сообщения одному процессору (представьте, что несколько параллельных веб-сканеров загружают страницы и отправляют результаты в очередь). Случай с врагами на экране выглядит по-другому - это множество объектов, реагирующих на один источник сообщений (движение игрока / время).
Другим примером, где тысячи MailboxProcessors - отличное решение, является связанный с вводом / выводом MailboxProcessor:
MailboxProcessor.Start(fun inbox ->
async {
while true do
let! message = inbox.Receive()
match message with
| ->
do! AsyncWrite("something")
let! response = AsyncResponse()
...
})
Здесь после получения сообщения агент очень быстро выдает поток, но ему все еще необходимо поддерживать состояние при асинхронных операциях. На практике это очень хорошо масштабируется - вы можете запускать тысячи и тысячи таких агентов: это отличный способ написать веб-сервер.