2011-04-07 3 views
11

C#에서 T의 MailboxProcessor를 사용해 보셨습니까? 샘플 코드를 게시 할 수 있습니까?MailboxProcessor <T> from C#

새 메시지를 어떻게 시작하고 메시지를 게시하며 어떻게 처리합니까?

답변

16

살펴보고,이 아니다 정말로 좋은 일 - 나는 호기심을 위해 주로 그것을 썼다.

MailboxProcessor<T> 형식은 F #에서 사용하도록 설계되었으므로 C# 프로그래밍 모델과 잘 맞지 않습니다. 아마도 C# 용 비슷한 API를 구현할 수는 있지만 멋지지 않을 것입니다 (C# 4.0에서는 그렇지 않음). TPL DataFlow library (CTP)은 futrue 버전의 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 번호 에이전트입니다. 이제 재미있는 비트는 C#에서 사용할 수있는 비동기 메서드 인 GetContent을 노출하는 다음 두 가지 방법입니다. 이 방법은 C 번호로부터 통상의 방법에 사용될 수 Task 객체 리턴

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

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

이것은 (등과 Task.WaitAll 같은 표준 방법을 사용) C# 4.0 합리적 사용할 수있을 것이다 그것은 심지어 좋을 것 C#의 다음 버전 인 C# await 키워드를 사용하여 작업을 수행 할 수 있습니다.

+0

자세한 답변 해 주셔서 감사합니다. 나는 그것을 한 번 줄 것이다! 한 조각이 누락되었습니다. C# 4.0의 실제 사용법입니다. – GregC

0

이 솔루션은 "CTP 비동기"는 C#을 필요로하지만 당신은 (는 C# async 확장을 사용)의 C#에서 직접 MailboxProcessor<T>를 사용할 수 있지만 내 다른 대답에 지적 Agent/MailboxProcessor in C# using new async/await

+0

내 손이 묶여 있으므로이 질문은 C# 4.0에 맞게 조정되었습니다. 나는 이것을 위해 가슴 뛰는 F #을 사용할 것이지만 나는 아직 할 수 없다. Async CTP에 go-live 라이센스가 있습니까? – GregC

+0

Tomas P.에서 지적했듯이이 문제의 핵심은 꼬리 재귀 호출에서 StackOverflowException을 일으킬 수 있다는 것입니다. 나는 대안을 찾고있다. – GregC

+0

@GregC, 아니요. go-live 라이센스가 없습니다. 이름에서 알 수 있듯이 미리보기 일 뿐이므로 제품을 사용하지 말아야합니다. –