【问题标题】:F# handling Task cancellationF# 处理任务取消
【发布时间】:2014-11-18 00:28:39
【问题描述】:

我很难理解为什么有些代码永远不会执行。

考虑这种扩展方法:

type WebSocketListener with
  member x.AsyncAcceptWebSocket = async {
    try
        let! client = Async.AwaitTask <| x.AcceptWebSocketAsync Async.DefaultCancellationToken
        if(not (isNull client)) then
            return Some client
        else
            return None
    with
        | :? System.Threading.Tasks.TaskCanceledException -> 
        | :? AggregateException ->
            return None
  }

我知道当取消令牌被取消时,AcceptSocketAsync 会抛出 TaskCanceledException。我已经签入了一个 C# 应用程序。这个想法是返回None

但是,这永远不会发生。如果我在最后一个return None 甚至if 表达式中放置一个断点,那么当取消令牌被取消时,它永远不会停在那里。而且我知道它正在 Async.AwaitTask 中等待,因为如果在取消之前,其他客户端连接,它会工作并在断点处停止。

我有点迷茫,为什么异常丢了?

【问题讨论】:

  • 你试过抓AggregateException吗?
  • 不错,不过我也试过了,还是不行。我更新了问题以添加AggregateException

标签: asynchronous f# f#-3.0 cancellationtokensource


【解决方案1】:

取消使用 F# 异步中的特殊路径 - Async.AwaitTask 会将已取消任务的执行重新路由到取消继续。如果您想要不同的行为 - 您始终可以手动执行此操作:

type WebSocketListener with
  member x.AsyncAcceptWebSocket = async {
    let! ct = Async.CancellationToken
    return! Async.FromContinuations(fun (s, e, c) ->
        x.AcceptWebSocketAsync(ct).ContinueWith(fun (t: System.Threading.Tasks.Task<_>) -> 
            if t.IsFaulted then e t.Exception
            elif t.IsCanceled then s None // take success path in case of cancellation
            else 
            match t.Result with
            | null -> s None
            | x -> s (Some x)
        )
        |> ignore
    )
  }

【讨论】:

  • 天哪......这太糟糕了。您说 Async.AwaitTask 会将执行重新路由到取消继续,我如何在那里捕获它?
  • 关于将 Task 的 CancelationToken 转换为 Async 的 CancelationToken 的任何想法?
猜你喜欢
  • 2012-09-19
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2015-12-07
  • 1970-01-01
  • 1970-01-01
  • 2015-03-20
  • 1970-01-01
相关资源
最近更新 更多