.net 通过忽略WCF呼叫取消

.net 通过忽略WCF呼叫取消,.net,wcf,asynchronous,task-parallel-library,.net,Wcf,Asynchronous,Task Parallel Library,我试图在WCF呼叫的客户端实现取消。我看到了很多关于取消服务器进程的问题,但我不需要这样做。我有一个UI,需要对取消长时间运行的服务器端进程作出响应 因此,我有以下代码: Const WayLongerThanItShouldEverTakeMilliseconds As Integer = 60 * 30 * 1000 Public Async Function CallService(token as CancellationToken) As Task(Of ReturnType)

我试图在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

它似乎起作用了。我不喜欢服务器的效果,虽然客户端在这里更重要。有什么我错过的比赛案例吗?我还没见过像这样的东西到处飘荡。

这是原样的。隔离和忽略无法取消的操作是一种常见的方法。我不太明白你想用
取消任务做什么。继续
。似乎不需要

请注意,您存在资源泄漏:许多
延迟
任务可能会累积,最终什么也不做。考虑在<代码> >任何< /COD>任务完成后取消延迟任务。释放内部资源(计时器)

我发现将所有这些逻辑打包成一个可重用的助手方法很有用。这样,您就可以轻松地为任何其他任务创建代理任务。如果您对实际操作的继续感到满意,那么您可以立即取消任何操作


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

<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

公共异步函数ToIgnorableTask(Of T)(originalTask作为Task(Of T),token作为CancellationToken)作为Task(Of T)
将internalCts用作新的CancellationTokenSource()
使用combinedCts作为CancellationTokenSource=CancellationTokenSource.CreateLinkedTokenSource(令牌,internalCts.token)
尝试
Dim cancellationTask As Task=Task.Delay(-1,combinedCts.Token)
等待任务。何时(原始任务、取消任务)
token.ThrowIfCancellationRequested()
返回等待原始任务
最后
internalCts.Cancel()
结束尝试
终端使用
终端使用
端函数
公共异步函数ToIgnorableTask(原始任务作为任务,令牌作为取消令牌)作为任务
将internalCts用作新的CancellationTokenSource()
使用combinedCts作为CancellationTokenSource=CancellationTokenSource.CreateLinkedTokenSource(令牌,internalCts.token)
尝试
Dim cancellationTask As Task=Task.Delay(-1,combinedCts.Token)
等待任务。何时(原始任务、取消任务)
token.ThrowIfCancellationRequested()
最后
internalCts.Cancel()
结束尝试
终端使用
终端使用
端函数

此操作按原样工作。隔离和忽略无法取消的操作是一种常见的方法。我不太明白你想用
取消任务做什么。继续
。似乎不需要

请注意,您存在资源泄漏:许多
延迟
任务可能会累积,最终什么也不做。考虑在<代码> >任何< /COD>任务完成后取消延迟任务。释放内部资源(计时器)

我发现将所有这些逻辑打包成一个可重用的助手方法很有用。这样,您就可以轻松地为任何其他任务创建代理任务。如果您对实际操作的继续感到满意,那么您可以立即取消任何操作


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

<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

公共异步函数ToIgnorableTask(Of T)(originalTask作为Task(Of T),token作为CancellationToken)作为Task(Of T)
将internalCts用作新的CancellationTokenSource()
使用combinedCts作为CancellationTokenSource=CancellationTokenSource.CreateLinkedTokenSource(令牌,internalCts.token)
尝试
Dim cancellationTask As Task=Task.Delay(-1,combinedCts.Token)
等待任务。何时(原始任务、取消任务)
token.ThrowIfCancellationRequested()
返回等待原始任务
最后
internalCts.Cancel()
结束尝试
终端使用
终端使用
端函数
公共异步函数ToIgnorableTask(原始任务作为任务,令牌作为取消令牌)作为任务
将internalCts用作新的CancellationTokenSource()
使用combinedCts作为CancellationTokenSource=CancellationTokenSource.CreateLinkedTokenSource(令牌,internalCts.token)
尝试
Dim cancellationTask As Task=Task.Delay(-1,combinedCts.Token)
等待任务。何时(原始任务、取消任务)
token.ThrowIfCancellationRequested()
最后
internalCts.Cancel()
结束尝试
终端使用
终端使用
端函数

谢谢您的更正。我认为如果没有ContinueWith continuation,则不会触发任何
时的
,我认为只有在任务完成到完成状态时才会触发它。感谢您的更正。我认为如果没有ContinueWith continuence,则不会触发任何
时的
,我认为只有当任务完成到完成状态时才会触发它。