我發現這個片段:Monadic重試邏輯W/F#和異步?
但我的工作不僅與retriable功能,而且還具有異步這樣,我想知道我是如何使這種類型的正確。我有一小塊monad,我想用它作爲異步計算的替代品,但它包含重試邏輯,我想知道如何將它們結合起來?
type AsyncRetryBuilder(retries) =
member x.Return a = a // Enable 'return'
member x.ReturnFrom a = x.Run a
member x.Delay f = f // Gets wrapped body and returns it (as it is)
// so that the body is passed to 'Run'
member x.Bind expr f = async {
let! tmp = expr
return tmp
}
member x.Zero = failwith "Zero"
member x.Run (f : unit -> Async<_>) : _ =
let rec loop = function
| 0, Some(ex) -> raise ex
| n, _ ->
try
async { let! v = f()
return v }
with ex -> loop (n-1, Some(ex))
loop(retries, None)
let asyncRetry = AsyncRetryBuilder(4)
消費碼是這樣的:
module Queue =
let desc (nm : NamespaceManager) name = asyncRetry {
let! exists = Async.FromBeginEnd(name, nm.BeginQueueExists, nm.EndQueueExists)
let beginCreate = nm.BeginCreateQueue : string * AsyncCallback * obj -> IAsyncResult
return! if exists then Async.FromBeginEnd(name, nm.BeginGetQueue, nm.EndGetQueue)
else Async.FromBeginEnd(name, beginCreate, nm.EndCreateQueue)
}
let recv (client : MessageReceiver) timeout =
let bRecv = client.BeginReceive : TimeSpan * AsyncCallback * obj -> IAsyncResult
asyncRetry {
let! res = Async.FromBeginEnd(timeout, bRecv, client.EndReceive)
return res }
錯誤是:
此表達預期具有類型
Async<'a>
但這裏已鍵入「B - >Async<'c>
如果發生錯誤(行)? – Daniel 2012-02-09 21:04:19
關於具體的錯誤,你的'Bind'應該把參數作爲一個元組(寫'x.Bind(expr,f)'而不是'x.Bind expr f')。這可能是原因。但是,它也不會使用'f',這是非常可疑的(並且你的'Return'類型是錯誤的)。 – 2012-02-09 21:19:34