非同期コンテキストでの例外処理
18363 ワード
⚠️ All of the observations and examples in this article are valid for .NET 5 and below.
例外処理に関しては、同期と非同期コンテキストにおけるcatch catchの基本的な違いは構文です.
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 :入れ子関数
最も内側の子関数が例外をスローしたときの非同期コンテキスト内のネストされた関数の場合、外部関数の実行のすべてをすぐに停止します(他の一般的な言語と同じように、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
この問題について(非同期コンテキストでの例外処理), 我々は、より多くの情報をここで見つけました https://dev.to/amoondria/f-exception-handling-in-asynchronous-context-14kdテキストは自由に共有またはコピーできます。ただし、このドキュメントのURLは参考URLとして残しておいてください。
Collection and Share based on the CC Protocol