다음 코드는 오류가 발생하면 작업을 시도하고 다시 시도합니다. 콘솔에 오류를 기록하는 함수를 호출하는 오류 콜백도 있습니다.비동기 메서드에서 로거 객체에 동기식으로 액세스 할 때 교착 상태가 발생합니다.
실행하면 콘솔에 오류가 한 번만 기록되고 프로그램이 일시 중지되면 주 스레드는 retryErrorForever
에서 차단되고 작업자 스레드는 차단되어 log
이됩니다.
하지만 왜?
module Program
type MyLogger(loggerName: string) =
member __.Warn fmt =
Printf.kprintf (printfn "%s: %s" loggerName) fmt
let log = MyLogger("Logger")
let retryErrorForever errorCallback retryTimeout work =
let rec loop() = async {
let! result = work
match result with
| Error e ->
errorCallback e
do! Async.Sleep retryTimeout
return! loop()
| Ok x -> return Ok x
}
loop()
let retryWorkUntilOk logError timeout (work: unit -> Result<string, string>) =
let workflow = async {
return work()
}
let result =
retryErrorForever logError timeout workflow
|> Async.RunSynchronously
match result with
| Ok x -> x
| Error e -> failwith <| sprintf "Cannot doWork: %s" e
let logError error =
log.Warn "%s" error
let doWork work =
retryWorkUntilOk logError 1000 work
let errorOnly() : Result<string, string> =
Error "You have no power here"
let result = doWork errorOnly
[<EntryPoint>]
let main _ =
printfn "%A" result
0
합니다. 또한 결과를 '게으른'것으로 만드는 것이 도움이됩니다. 고맙습니다 –