相关疑难解决方法(0)

已取消的任务不会将控制权返回到异步块

我试图把它减少到尽可能小的重复,但它仍然有点长,我道歉.

我有一个F#项目引用一个C#项目,代码如下所示.

public static class CSharpClass {
    public static async Task AsyncMethod(CancellationToken cancellationToken) {
        await Task.Delay(3000);
        cancellationToken.ThrowIfCancellationRequested();
    }
}
Run Code Online (Sandbox Code Playgroud)

这是F#代码.

type Message = 
    | Work of CancellationToken
    | Quit of AsyncReplyChannel<unit>

let mkAgent() = MailboxProcessor.Start <| fun inbox -> 
    let rec loop() = async {
        let! msg = inbox.TryReceive(250)
        match msg with
        | Some (Work cancellationToken) ->
            let! result = 
                CSharpClass.AsyncMethod(cancellationToken)
                |> Async.AwaitTask
                |> Async.Catch
            // THIS POINT IS NEVER REACHED AFTER CANCELLATION
            match result with
            | Choice1Of2 _ -> …
Run Code Online (Sandbox Code Playgroud)

f# asynchronous task cancellation mailboxprocessor

7
推荐指数
1
解决办法
109
查看次数

Async.Catch不适用于OperationCanceledExceptions

我使用Async.Catch来处理异步工作流抛出的异常:

work
|> Async.Catch
|> Async.RunSynchronously
|> fun x -> match x with
            | Choice1Of2 _ -> () // success
            | Choice2Of2 ex -> // failure, handle exception
Run Code Online (Sandbox Code Playgroud)

今天我注意到Async.Catch不处理OperationCanceledExceptions.而不是从Async.Catch获得选择,异常不断冒泡直到它击中我.我希望下面的测试是红色的,但它是绿色的:

  [<Test>]
  let ``Async.Catch doesnt work on OperationCancelledExceptions``() =
    use cancellationTokenSource = new System.Threading.CancellationTokenSource(1000)

    let work = async {
      while true do
        do! Async.Sleep 100
    }

    (fun () -> work
               |> Async.Catch
               |> fun x -> Async.RunSynchronously (x, cancellationToken=cancellationTokenSource.Token)
               |> ignore)
    |> should throw typeof<System.OperationCanceledException>
Run Code Online (Sandbox Code Playgroud)

使用Async.Catch + Choices +匹配以及其他一些使用try/catch块评估一些异常似乎不正确......它看起来像下面这样,这太复杂了.除此之外,我想知道Async.Catch有什么用,因为我必须使用try/catch块...:

  [<Test>]
  let ``evaluating …
Run Code Online (Sandbox Code Playgroud)

f# exception-handling async-workflow

6
推荐指数
1
解决办法
944
查看次数