MailboxProcessor <T> от С#

Вы пытались использовать MailboxProcessor из T с С#? Не могли бы вы разместить образец кода?

Как вы начинаете новый, публикуете сообщения и как их обрабатываете?

Ответ 1

В то время как вы можете использовать MailboxProcessor<T> непосредственно из С# (используя расширение С# async), как указано в моем другом ответе, это не очень хорошо - я написал это в основном для любопытства.

Тип MailboxProcessor<T> был разработан для использования с F #, поэтому он не подходит для модели программирования С#. Возможно, вы могли бы реализовать аналогичный API для С#, но это было бы не так хорошо (конечно, не в С# 4.0). библиотека TPL DataFlow (CTP) обеспечивает аналогичный дизайн для версии Futrue С#.

В настоящее время лучше всего реализовать агент с помощью MailboxProcessor<T> в F # и сделать его удобным для использования С# с помощью Task. Таким образом, вы можете реализовать основные части агентов в F # (используя хвостовую рекурсию и асинхронные рабочие процессы), а затем составить и использовать их с С#.

Я знаю, что это не может напрямую ответить на ваш вопрос, но я думаю, что стоит привести пример, потому что это действительно единственный разумный способ объединить агентов F # (MailboxProcessor) с С#. Недавно я написал простую демонстрацию "чат-комнаты", вот пример:

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 как асинхронный метод, который можно использовать из С#. Метод возвращает объект Task, который может использоваться обычным образом из С#:

  member x.GetContentAsync() = 
    Async.StartAsTask(agent.PostAndAsyncReply(GetContent))

  member x.GetContentAsync(cancellationToken) = 
    Async.StartAsTask
     ( agent.PostAndAsyncReply(GetContent), 
       cancellationToken = cancellationToken )

Это будет разумно использоваться с С# 4.0 (с использованием стандартных методов, таких как Task.WaitAll и т.д.), и это будет еще лучше в следующей версии С#, когда вы сможете использовать ключевое слово С# await для работы с задачами.