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