nullになるネストされたAsyncを呼び出すときに問題が発生しました。例外が発生しますが、非同期ワークフローが提供する通常の例外処理メソッドではキャッチできません。非同期の例外処理で予期しない動作が発生する可能性がありますか?
は、次のような問題を再現する簡単なテストです:
follwing例外が発生[<Test>]
let ``Nested async is null with try-with``() =
let g(): Async<unit> = Unchecked.defaultof<Async<unit>>
let f = async {
try
do! g()
with e ->
printf "%A" e
}
f |> Async.RunSynchronously |> ignore
:
System.NullReferenceException : Object reference not set to an instance of an object.
at [email protected](AsyncParams`1 args)
at <StartupCode$FSharp-Core>[email protected](Trampoline this, FSharpFunc`2 action)
at Microsoft.FSharp.Control.Trampoline.ExecuteAction(FSharpFunc`2 firstAction)
at Microsoft.FSharp.Control.TrampolineHolder.Protect(FSharpFunc`2 firstAction)
at Microsoft.FSharp.Control.AsyncBuilderImpl.startAsync(CancellationToken cancellationToken, FSharpFunc`2 cont, FSharpFunc`2 econt, FSharpFunc`2 ccont, FSharpAsync`1 p)
at [email protected]oke(CancellationToken cancellationToken, FSharpFunc`2 cont, FSharpFunc`2 econt, FSharpFunc`2 ccont, FSharpAsync`1 p)
at Microsoft.FSharp.Control.CancellationTokenOps.RunSynchronously(CancellationToken token, FSharpAsync`1 computation, FSharpOption`1 timeout)
at Microsoft.FSharp.Control.FSharpAsync.RunSynchronously(FSharpAsync`1 computation, FSharpOption`1 timeout, FSharpOption`1 cancellationToken)
at Prioinfo.Urkund.DocCheck3.Core2.Tests.AsyncTests.Nested async is null with try-with() in SystemTests.fs: line 345
私は本当に例外が、この場合に巻き込まれるべきだと思う、またはある
これは本当に期待される行動ですか?例外がバインドに内上げているようだ
[<Test>]
let ``Nested async is null with Async.Catch``() =
let g(): Async<unit> = Unchecked.defaultof<Async<unit>>
let f = async {
do! g()
}
f |> Async.Catch |> Async.RunSynchronously |> ignore
[<Test>]
let ``Nested async is null with StartWithContinuations``() =
let g(): Async<unit> = Unchecked.defaultof<Async<unit>>
let f = async {
do! g()
}
Async.StartWithContinuations(f
, fun _ ->()
, fun e -> printfn "%A" e
, fun _ ->())
:
また、Async.Catch
とAsync.StartWithContinuations
展示これらのテストケースによって示されるように、同じ問題を(私は、Visual Studioにレコードの2010 SP1を使用しています)メソッドを使用すると、結果として通常のエラー処理コードがバイパスされることになります。ドキュメントや他の場所に何も見つからないので、これが意図された動作であることを示唆しているので、私には非同期ワークフローの実装におけるバグのように見えます。
ほとんどの場合、回避するのは簡単ですが、少なくとも私にとっては大きな問題ではないと思いますが、非同期の例外処理メカニズムを完全に信用できないため、少し不安ですすべての例外をキャプチャします。
編集:
それを私がKVBに同意するいくつかの考えを与えた後。 null非同期は通常のコードでは実際には存在すべきではありません。実際には、(Unchecked.defaultOfを使用するなどしてはいけない)何かをしたり、リフレクションを使って値を生成したりするだけの場合にしか生成できません(私の場合、 。したがって、実際にはバグではありませんが、もっと重要なケースです。
VSでデバッグするときとエクスプローラで起動したときの両方で、FSIとコンソールアプリケーションで再現できます。だからそれは一貫しているようだ –
Option.Noneは、基本的にnullです。だからAsync <'a option>この問題があるようです。 – Hans