MailboxProcessor <T>из C # - PullRequest
       52

MailboxProcessor <T>из C #

12 голосов
/ 07 апреля 2011

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

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

Ответы [ 2 ]

17 голосов
/ 08 апреля 2011

Хотя вы можете использовать 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 для работы с задачами.

0 голосов
/ 07 апреля 2011

Для этого решения требуется C # «асинхронная CTP», но взгляните на Agent / MailboxProcessor в C # с использованием нового async / await

...