Хотя вы можете использовать MailboxProcessor<T>
непосредственно из C # (используя расширение C # async
), как указано в моем другом ответе, это не очень хорошая вещь - я написал это в основном для любопытства.
Тип MailboxProcessor<T>
был разработан для использования с F #, поэтому он не очень подходит для модели программирования C #.Вероятно, вы могли бы реализовать подобный API для C #, но это было бы не очень хорошо (конечно, не в C # 4.0).Библиотека TPL DataFlow (CTP) обеспечивает аналогичный дизайн для будущей версии C #.
В настоящее время лучше всего реализовать агент, использующий MailboxProcessor<T>
в F #, и сделать егодружественный к использованию C # с помощью Task
.Таким образом, вы можете реализовать основные части агентов в F # (используя хвостовую рекурсию и асинхронные рабочие процессы), а затем составить и использовать их из C #.
Я знаю, что это может не дать прямого ответа на ваш вопрос, но я думаю,Стоит привести пример - потому что это действительно единственный разумный способ объединения агентов F # (MailboxProcessor
) с C #.Недавно я написал простую демоверсию "чата", так что вот пример:
type internal ChatMessage =
| GetContent of AsyncReplyChannel<string>
| SendMessage of string
type ChatRoom() =
let agent = Agent.Start(fun agent ->
let rec loop messages = async {
// Pick next message from the mailbox
let! msg = agent.Receive()
match msg with
| SendMessage msg ->
// Add message to the list & continue
let msg = XElement(XName.Get("li"), msg)
return! loop (msg :: messages)
| GetContent reply ->
// Generate HTML with messages
let html = XElement(XName.Get("ul"), messages)
// Send it back as the reply
reply.Reply(html.ToString())
return! loop messages }
loop [] )
member x.SendMessage(msg) = agent.Post(SendMessage msg)
member x.AsyncGetContent() = agent.PostAndAsyncReply(GetContent)
member x.GetContent() = agent.PostAndReply(GetContent)
Пока что это просто стандартный агент F #.Теперь интересными битами являются следующие два метода, которые представляют GetContent
как асинхронный метод, используемый из C #.Метод возвращает объект Task
, который можно использовать обычным способом из C #:
member x.GetContentAsync() =
Async.StartAsTask(agent.PostAndAsyncReply(GetContent))
member x.GetContentAsync(cancellationToken) =
Async.StartAsTask
( agent.PostAndAsyncReply(GetContent),
cancellationToken = cancellationToken )
Это будет разумно использоваться из C # 4.0 (с использованием стандартных методов, таких как Task.WaitAll
и т. Д.) Иэто будет еще лучше в следующей версии C #, когда вы сможете использовать ключевое слово C # await
для работы с задачами.