비동기 컨텍스트에서 F# 예외 처리
18718 단어 dotnetfsharpprogrammingbeginners
⚠️ All of the observations and examples in this article are valid for .NET 5 and below.
예외 처리와 관련하여 동기 및 비동기 컨텍스트에서 예외를 포착하는 것의 근본적인 차이점은 구문:
try-with
대 Async.Catch
입니다.다음 몇 가지 예에서는 이러한 차이점과 비동기 컨텍스트 내에서 예외 처리의 적절한 사용법을 보여줍니다.
비동기 캐치
Async.Catch
비동기 작업 흐름 내에서 예외를 포착할 수 있는 비동기 계산을 생성합니다. Async<Choice<'T, exn>>
를 반환하여 수행합니다. 여기서 'T
는비동기 워크플로우 및
exn
는 예외입니다.이 결과 값은 패턴 매칭을 통해 추출할 수 있습니다.
다음을 기억하는 것이 중요합니다.
Choice1Of2
가 결과 값으로 반환됩니다. Choice2Of2
가 반환됩니다. 비동기 워크플로에서
Async.Catch
를 어떻게 사용할 수 있는지 살펴보겠습니다.예시 1. 예상 결과 처리 방법
이 예에서는
Async.Catch
가 예상 결과를 반환할 때(예외가 아닌 경우) someAsyncFunction
를 사용하는 방법을 보여줍니다.someAsyncFunction
가 완료되면 functionExec
가 패턴 일치를 수행하여 Choice1Of2
가 반환된 다음 콘솔에 인쇄됩니다.
let someAsyncFunction(raiseException: bool) : Async<unit> =
async {
printfn ("Starting someAsyncFunction...")
do! Async.Sleep(1000)
if(raiseException) then
raise (System.Exception("someAsyncFunction threw Exception"))
}
let functionExec(raiseException: bool) : Async<string> =
async{
let! result = someAsyncFunction(raiseException) |> Async.Catch
return match result with
| Choice1Of2 _ -> "Result from someAsyncFunction"
| Choice2Of2 ex -> ex.Message
}
let main() =
async{
let! result = functionExec(false)
printfn($"{result}")
}
Async.Start(main())
Async.Sleep 1000 |> Async.RunSynchronously
콘솔 출력
Starting someAsyncFunction...
Result from someAsyncFunction
예시 2. 예외 결과 처리 방법
이 예는
Async.Catch
에서 예외가 발생했을 때 someAsyncFunction
를 사용하는 방법을 보여줍니다.someAsyncFunction
에서 예외functionExec
가 발생하면 패턴 일치를 수행하여 Choice2Of2
(예외)가 반환된 다음 콘솔에 인쇄됩니다.
let someAsyncFunction(raiseException: bool) : Async<unit> =
async {
printfn ("Starting someAsyncFunction...")
do! Async.Sleep(1000)
if(raiseException) then
raise (System.Exception("someAsyncFunction threw Exception"))
}
let functionExec(raiseException: bool) : Async<string> =
async{
let! result = someAsyncFunction(raiseException) |> Async.Catch
return match result with
| Choice1Of2 _ -> "Result from someAsyncFunction"
| Choice2Of2 ex -> ex.Message
}
let main() =
async{
let! result = functionExec(true)
printfn($"{result}")
}
Async.Start(main())
Async.Sleep 1000 |> Async.RunSynchronously
콘솔 출력
Starting someAsyncFunction...
someAsyncFunction threw Exception
예제 3: 중첩 함수
비동기 컨텍스트 내의 중첩 함수의 경우 가장 내부 자식 함수가 예외를 throw하면 외부 함수의 모든 실행이 즉시 중지됩니다(C#과 같은 다른 인기 있는 언어와 마찬가지로).
다음 예제에서는 이것이 어떻게 보이는지 보여줍니다.
let someChildAsyncFunction(raiseException: bool) : Async<unit> =
async{
printfn("Starting someChildAsyncFunction...")
do! Async.Sleep(1000)
if(raiseException) then
raise (System.Exception("someChildAsyncFunction raised Exception"))
}
let someAsyncFunction(raiseException: bool) : Async<unit> =
async {
printfn ("Starting someAsyncFunction...")
do! someChildAsyncFunction(raiseException)
printfn ("Ending someAsyncFunction...")
}
let functionExec(raiseException: bool) : Async<string> =
async{
let! result = someAsyncFunction(raiseException) |> Async.Catch
return match result with
| Choice1Of2 _ -> "Some result"
| Choice2Of2 ex -> ex.Message
}
let main() =
async{
let! result = functionExec(true)
printfn($"{result}")
}
Async.Start(main())
Async.Sleep 1000 |> Async.RunSynchronously
콘솔 출력
Starting someAsyncFunction...
Starting someChildAsyncFunction...
someChildAsyncFunction raised Exception
someChildAsyncFunction
예외가 발생하면 호출자someAsyncFunction
의 추가 실행도 종료된다는 것을 콘솔에서 볼 수 있습니다.시도
이제
Async.Catch
가 비동기 컨텍스트 내에서 try-with
를 사용하려고 하면 어떻게 되는지 살펴보겠습니다.
let someAsyncFunction() : Async<unit> =
async {
printfn ("Starting someAsyncFunction...")
do! Async.Sleep(1000)
raise (System.Exception("someAsyncFunction threw Exception"))
}
try
Async.Start(someAsyncFunction())
with
| Failure message -> printfn($"{message}")
printfn("Hello, this example will blow up")
콘솔 출력
Starting someAsyncFunction...
Unhandled exception. System.Exception: someAsyncFunction threw Exception
at [email protected](Unit _arg1)
at Microsoft.FSharp.Control.AsyncPrimitives.CallThenInvokeNoHijackCheck[a,b](AsyncActivation`1 ctxt, b result1, FSharpFunc`2 userCode) in D:\a\_work\1\s\src\fsharp\FSharp.Core\async.fs:line 464
at Microsoft.FSharp.Control.Trampoline.Execute(FSharpFunc`2 firstAction) in D:\a\_work\1\s\src\fsharp\FSharp.Core\async.fs:line 139
--- End of stack trace from previous location ---
at [email protected](ExceptionDispatchInfo edi)
at Microsoft.FSharp.Control.Trampoline.Execute(FSharpFunc`2 firstAction) in D:\a\_work\1\s\src\fsharp\FSharp.Core\async.fs:line 139
at <StartupCode$FSharp-Core>[email protected](Object _arg2) in D:\a\_work\1\s\src\fsharp\FSharp.Core\async.fs:line 1609
at System.Threading.TimerQueueTimer.<>c.<.cctor>b__27_0(Object state)
at System.Threading.ExecutionContext.RunInternal(ExecutionContext executionContext, ContextCallback callback, Object state)
--- End of stack trace from previous location ---
at System.Threading.ExecutionContext.RunInternal(ExecutionContext executionContext, ContextCallback callback, Object state)
at System.Threading.TimerQueueTimer.CallCallback(Boolean isThreadPool)
at System.Threading.TimerQueueTimer.Fire(Boolean isThreadPool)
at System.Threading.TimerQueue.FireNextTimers()
at System.Threading.TimerQueue.AppDomainTimerCallback(Int32 id)
Process finished with exit code 134 (interrupted by signal 6: SIGABRT)
콘솔 출력은
try-with
를 사용하여 처리되지 않은 예외가 발생했음을 보여줍니다. 여기서 일어나는 일은 someAsyncFucntion
가 실행되는 스레드 풀에서 예외가 발생한다는 것입니다.스레드 풀에서 처리되지 않은 예외는
Async.Start
로 전파되지 않고 try-with
블록에 도달하지 않는 프로세스를 종료합니다. (출처: MSDN - Exceptions in managed threads & Stack Overflow ).참조
MSDN - Exceptions in managed threads
Stack Overflow
Reference
이 문제에 관하여(비동기 컨텍스트에서 F# 예외 처리), 우리는 이곳에서 더 많은 자료를 발견하고 링크를 클릭하여 보았다 https://dev.to/amoondria/f-exception-handling-in-asynchronous-context-14kd텍스트를 자유롭게 공유하거나 복사할 수 있습니다.하지만 이 문서의 URL은 참조 URL로 남겨 두십시오.
우수한 개발자 콘텐츠 발견에 전념 (Collection and Share based on the CC Protocol.)