通过忽略 WCF 调用取消



我正在尝试在 WCF 调用的客户端实现取消。我已经看到许多关于取消服务器进程的问题,但我不需要这样做。我有一个 UI 需要响应取消长时间运行的服务器端进程。

所以我有以下代码:

Const WayLongerThanItShouldEverTakeMilliseconds As Integer = 60 * 30 * 1000
Public Async Function CallService(token as CancellationToken) As Task(Of ReturnType)
    Dim client As IWcfService = _service
    Dim returnTask As Task(Of ReturnType) = client.FunctionAsync()
    Dim cancellationTask as Task = Task.Delay(WayLongerThanItShouldEverTakeMilliseconds, token).
       ContinueWith(Function(t) Task.FromCanceled(token), TaskContinuationOptions.OnlyOnCanceled)
    Await Task.WhenAny(returnTask, cancellationTask)
    token.ThrowIfCancellationRequested()
    Return Await returnTask
End Function

它似乎有效。我不喜欢服务器效果,尽管客户端在这里更重要。我错过了一些比赛案例吗?我还没有看到这样的东西漂浮在周围。

这按原样工作。隔离和忽略无法取消的操作是一种常用方法。我不太明白你想用cancellationTask.ContinueWith做什么.似乎不需要。

请注意,您有资源泄漏:许多Delay任务可能会累积并最终什么都不做。请考虑在WhenAny任务完成后取消延迟任务。这将释放内部资源(计时器)。

我发现将所有这些逻辑打包到一个可重用的帮助程序方法中很有用。这样,您可以轻松地为任何其他任务创建代理任务。然后,如果您同意实际操作继续,您可以立即取消任何操作。


编辑:为未来用户添加了扩展:

<Extension()>
Public Async Function ToIgnorableTask(Of T)(originalTask As Task(Of T), token As CancellationToken) As Task(Of T)
    Using internalCts As New CancellationTokenSource()
        Using combinedCts As CancellationTokenSource = CancellationTokenSource.CreateLinkedTokenSource(token, internalCts.Token)
            Try
                Dim cancellationTask As Task = task.Delay(-1, combinedCts.Token)
                Await Task.WhenAny(originalTask, cancellationTask)
                token.ThrowIfCancellationRequested()
                Return Await originalTask
            Finally
                internalCts.Cancel()
            End Try
        End Using
    End Using
End Function
<Extension()>
Public Async Function ToIgnorableTask(originalTask As Task, token As CancellationToken) As Task
    Using internalCts As New CancellationTokenSource()
        Using combinedCts As CancellationTokenSource = CancellationTokenSource.CreateLinkedTokenSource(token, internalCts.Token)
            Try
                Dim cancellationTask As Task = Task.Delay(-1, combinedCts.Token)
                Await Task.WhenAny(originalTask, cancellationTask)
                token.ThrowIfCancellationRequested()
            Finally
                internalCts.Cancel()
            End Try
        End Using
    End Using
End Function

最新更新