您是否尝试过使用C#中的T的MailboxProcessor?您可以发布示例代码吗?

您如何启动一个新的,向其发布消息以及如何处理它们?

最佳答案

正如您在其他答案中所指出的那样,虽然您可以直接从C#使用MailboxProcessor<T>(使用C#async扩展名),但这并不是一件好事-我主要是出于好奇而写的。
MailboxProcessor<T>类型设计用于F#,因此与C#编程模型不太匹配。您可能可以为C#实现类似的API,但这并不是很好(肯定不是在C#4.0中)。 TPL DataFlow library (CTP)为C#的完整版本提供了类似的设计。

当前,最好的办法是在F#中使用MailboxProcessor<T>实现代理,并通过使用Task使它对C#使用友好。这样,您可以在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#await关键字来处理任务时,在下一版本的C#中甚至会更好。

关于c#-4.0 - 来自C#的MailboxProcessor <T>,我们在Stack Overflow上找到一个类似的问题:https://stackoverflow.com/questions/5581701/

10-10 03:36