找到Microsoft.FSharp.Control.Trampoline引发的异常

Wal*_*lly 5 f# asynchronous

我负责F#WPF应用程序。当发生未处理的异常时,它将通过电子邮件发送给我。大多数时候,我能够从错误消息和堆栈跟踪中识别异常的来源。但是,我偶尔会收到类似以下的消息,该消息在堆栈跟踪中不包含我的任何代码。

Summary:
Object reference not set to an instance of an object.
--------------
Details:

System.NullReferenceException: 
Object reference not set to an instance of an object.
   at Microsoft.FSharp.Control.CancellationTokenOps.Start@1234-1.Invoke(Exception e)
   at <StartupCode$FSharp-Core>.$Control.loop@435-40(Trampoline this, FSharpFunc`2 action)
   at Microsoft.FSharp.Control.Trampoline.ExecuteAction(FSharpFunc`2 firstAction)
   at Microsoft.FSharp.Control.TrampolineHolder.Protect(FSharpFunc`2 firstAction)
   at <StartupCode$FSharp-Core>.$Control.-ctor@520-1.Invoke(Object state)
   at System.Threading.QueueUserWorkItemCallback.WaitCallback_Context(Object state)
   at System.Threading.ExecutionContext.RunInternal(ExecutionContext executionContext, ContextCallback callback, Object state, Boolean preserveSyncCtx)
   at System.Threading.ExecutionContext.Run(ExecutionContext executionContext, ContextCallback callback, Object state, Boolean preserveSyncCtx)
   at System.Threading.QueueUserWorkItemCallback.System.Threading.IThreadPoolWorkItem.ExecuteWorkItem()
   at System.Threading.ThreadPoolWorkQueue.Dispatch()
   at System.Threading._ThreadPoolWaitCallback.PerformWaitCallback()
Run Code Online (Sandbox Code Playgroud)

此堆栈跟踪中有哪些线索可以帮助我识别此异常的来源?

例如,我假设原始异常正在async计算中抛出。(我的大部分异步代码都是基于F#异步块的。)我NullReferenceException可能发生在async块中的任何地方吗?我注意到该异常发生在Start()方法内。还是?该Start()方法采用一个Exception实例,因此可能在此之前引发了异常。这告诉我什么吗?我想知道是否有人足够熟悉,Microsoft.FSharp.Control.Trampoline以指出正确的方向。

顺便说一句,在我的错误处理代码中,我会仔细检查所有InnerExceptions和处理AggregateExceptions。因此,我认为这是Exception实例中所有可用的信息,但我可能是错的。

Wal*_*lly 5

我做了一个快速测试。以下控制台程序生成相同的堆栈跟踪。

[<EntryPoint>]
let main argv = 

    async { printfn "Inside async block."
            let o = null
            o.GetType() |> ignore
    } |> Async.Start

    System.Console.ReadKey(true) |> ignore
    0 // return an integer exit code
Run Code Online (Sandbox Code Playgroud)

这告诉我以下内容:

  1. 神秘异常发生在异步块中。
  2. 它可能发生在异步块中的任何地方。
  3. 诊断的唯一方法是改进异步块周围的错误处理(可能使用 Async.Catch)并重新部署应用程序的新版本并等待它再次发生。