Gre*_*egC 12 concurrency f# c#-to-f# c#-4.0 mailboxprocessor
您是否尝试过使用C#的T的MailboxProcessor?你能发贴示例代码吗?
你如何开始一个新的,发布消息,以及如何处理它们?
Tom*_*cek 17
虽然您可以MailboxProcessor<T>直接使用C#(使用C#async扩展名),但在我的另一个答案中指出,这不是一件好事 - 我写的主要是为了好奇.
该MailboxProcessor<T>类型设计用于F#,因此它不适合C#编程模型.您可能可以为C#实现类似的API,但它不会那么好(当然不是在C#4.0中).该TPL数据流库(CTP)提供C#的futrue版本类似的设计.
目前,最好的办法是使用MailboxProcessor<T>F#实现代理,并通过使用使其对C#的使用友好Task.这样,您可以在F#中实现代理的核心部分(使用尾递归和异步工作流),然后从C#中编写和使用它们.
我知道这可能不会直接回答你的问题,但我认为值得举一个例子 - 因为这是将F#agents(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)
Run Code Online (Sandbox Code Playgroud)
到目前为止,这只是一个标准的F#代理.现在,有趣的位是以下两种方法,它们GetContent作为可从C#使用的异步方法公开.该方法返回Task对象,可以通常的方式从C#中使用:
member x.GetContentAsync() =
Async.StartAsTask(agent.PostAndAsyncReply(GetContent))
member x.GetContentAsync(cancellationToken) =
Async.StartAsTask
( agent.PostAndAsyncReply(GetContent),
cancellationToken = cancellationToken )
Run Code Online (Sandbox Code Playgroud)
这将在C#4.0中合理使用(使用诸如此类的标准方法Task.WaitAll),并且在下一版本的C#中,当您能够使用C#await关键字处理任务时,它将更加出色.