【问题标题】:Async.Await not catching Task exceptionAsync.Await 未捕获任务异常
【发布时间】:2014-10-05 03:26:26
【问题描述】:

我有一个不返回任何内容的任务。您不能对此类任务执行 Async.AwaitTask,因此您需要改为执行 Async.AwaitIAsyncTask。不幸的是,这似乎只是吞噬了底层任务抛出的任何异常:-

TaskFactory().StartNew(Action(fun _ -> failwith "oops"))
|> Async.AwaitIAsyncResult
|> Async.Ignore
|> Async.RunSynchronously

// val it : unit = ()

另一方面,AwaitTask 正确地级联异常:-

TaskFactory().StartNew(fun _ -> failwith "oops"                               
                                5)
|> Async.AwaitTask
|> Async.Ignore
|> Async.RunSynchronously

// POP!

将常规(非通用)任务视为异步但仍会传播异常的最佳方法是什么?

【问题讨论】:

    标签: exception-handling f# task-parallel-library f#-async


    【解决方案1】:

    作为正确处理取消的选项:

    open System.Threading.Tasks
    
    module Async =
        let AwaitTask (t: Task) = 
            Async.FromContinuations(fun (s, e, c) ->
                t.ContinueWith(fun t -> 
                    if t.IsCompleted then s()
                    elif t.IsFaulted then e(t.Exception)
                    else c(System.OperationCanceledException())
                    )
                |> ignore
            )
    

    【讨论】:

    • 稍微修正一下,IsCompleted检查必须在IsFaulted检查之后进行,因为一个故障也被认为已经完成。
    【解决方案2】:

    来自Xamarin F# Shirt App(我最初是从 Dave Thomas 那里借来的):

    [<AutoOpen>]
    module Async =
         let inline awaitPlainTask (task: Task) = 
            // rethrow exception from preceding task if it faulted
            let continuation (t : Task) = if t.IsFaulted then raise t.Exception
            task.ContinueWith continuation |> Async.AwaitTask
    

    【讨论】:

    • let continuation (t : Task) = if t.IsFaulted then raise t.Exception 可能更清楚。
    • @Daniel 随时让它变得更好。 :-) 我对我的答案没有占有欲!
    • 我第一次看到这里:theburningmonk.com/2012/10/…
    • 缺点:取消处理不当,重新引发异常会丢弃堆栈跟踪
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2023-03-30
    • 1970-01-01
    • 1970-01-01
    • 2015-02-17
    • 2017-03-23
    • 1970-01-01
    • 2022-10-02
    相关资源
    最近更新 更多