2011-04-07 28 views
11

C# adresinden bir Posta Kutusu İşlemcisi'ni kullanmaya çalıştınız mı? Örnek kod gönderebilir misiniz?MailboxProcessor <T> C#

Yeni bir tane nasıl başlatırsınız, mesajlar gönderiyor ve bunları nasıl işliyorsunuz?

cevap

16

bakmak, bu değil Gerçekten iyi bir şey - Ben özellikle merak için yazdım.

MailboxProcessor<T> türü F # 'den kullanılacak şekilde tasarlanmıştır, bu nedenle C# programlama modeline uygun değildir. Muhtemelen C# için benzer bir API uygulayabilirsiniz, ancak bu hoş olmaz (kesinlikle C# 4.0'da değil). TPL DataFlow library (CTP), C# 'un sonraki sürümü için benzer bir tasarım sunar.

Şu anda yapılacak en iyi şey, MailboxProcessor<T> F # öğelerini kullanarak aracı uygulamak ve Task kullanarak C# kullanımı için kolaylık sağlamaktır. Böylelikle, ajanların çekirdek parçalarını F # (kuyruk geri çekme ve uyumsuz iş akışlarını kullanarak) uygulayabilir ve daha sonra bunları & C# 'dan kullanabilirsiniz.

Bu sorunun doğrudan sorunuzu yanıtlayamayacağını biliyorum, ancak bir örnek vermeye değer olduğunu düşünüyorum - çünkü bu gerçekten F # ajanlarını (MailboxProcessor) C# ile birleştirmenin tek mantıklı yolu. Ben işte, geçenlerde basit bir "sohbet odası" demo yazdığı bir örnek:

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) 

Şimdiye kadar, bu sadece standart F # ajandır. Şimdi, ilginç bitler, GetContent'u C# 'den kullanılabilen bir eşzamansız yöntem olarak gösteren aşağıdaki iki yöntemdir. yöntem, C# alışılmış bir şekilde kullanılabilir Task nesne döndürür:

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

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

Bu, (örneğin, vb Task.WaitAll gibi standart yöntemler kullanılarak) C# 4.0, makul kullanılabilir olacak ve daha da iyi olacaktır C# sonraki sürümü C# await anahtar sözcüğü ile görevler ile çalışmak mümkün olacak.

+0

Detaylı cevabınız için teşekkür ederiz. Bir şans vereceğim! Tek parça eksik - C# 4.0'dan gerçek kullanım. – GregC

0

Bu çözüm "CTP zaman uyumsuz" C# gerektirir ama (C# async uzantısını kullanarak) C# doğrudan MailboxProcessor<T> kullanabilirsiniz ancak benim diğer yanıtında belirttiği gibi Agent/MailboxProcessor in C# using new async/await

+0

Soru: Özellikle ellerim bağlı olduğundan C# 4.0'a doğru ilerliyor. Bunun için bir kalp atışında F # kullanırdım, ama henüz yapamam. Async CTP'nin canlı bir lisansı var mı? – GregC

+0

Tomas P.'nin belirttiği gibi, bu problemin özü, StackOverflowException'a neden olan kuyruk özyinelemeli aramada olurdu. Alternatifler arıyorum. – GregC

+0

@GregC, no go-live lisansına sahip değil. Sadece bir önizleme, isminden de anlaşılacağı gibi, –

İlgili konular