我目前正在我的应用中使用.NET Cancellation Framework。看来我需要时不时地使用链接的CancellationTokenSource
,并且我发现在每个匹配的catch中“展开”OperationCanceledException
以使其包含正确的CancellationToken
是单调乏味的。我想问一下:
我的问题是关于.NET 4.我还附上代码示例,显示我在说什么:
Using linkedCts = CancellationTokenSource.CreateLinkedTokenSource(externalCancelToken, internalCancelToken) Try myRequest.Dispatch(linkedCts.Token) Catch ex As WebException When ex.Status = WebExceptionStatus.RequestCanceled If externalCancelToken.IsCancellationRequested Then Throw New OperationCanceledException(externalCancelToken) ElseIf internalCancelToken.IsCancellationRequested Then Throw New OperationCanceledException(internalCancelToken) Else Throw End If Catch ex As OperationCanceledException If ex.CancellationToken = linkedCts.Token Then If externalCancelToken.IsCancellationRequested Then Throw New OperationCanceledException(Nothing, ex, externalCancelToken) ElseIf internalCancelToken.IsCancellationRequested Then Throw New OperationCanceledException(Nothing, ex, internalCancelToken) End If End If End Try End Using
答案 0 :(得分:0)
我试图谷歌一些想法,但没有发现任何东西。所以我想出了以下链接CancellationTokenSource
- es:
Imports System.Threading Namespace Threading Public Class LinkedCancellationTokenSource Implements IDisposable Public ReadOnly Property Token As CancellationToken Get Return Me.internalSource.Token End Get End Property Public ReadOnly Property IsCancellationRequested As Boolean Get Return Me.internalSource.IsCancellationRequested End Get End Property Private ReadOnly tokens As CancellationToken() Private ReadOnly internalSource As CancellationTokenSource Private Sub New(internalSource As CancellationTokenSource, tokens As CancellationToken()) Me.internalSource = internalSource Me.tokens = tokens End Sub Public Sub Cancel() Me.internalSource.Cancel() End Sub ''' ''' Tries to unwrap to any contained ''' in this source. If token in exception is unknown, ''' nothing will be thrown and you have to elevate. ''' ''' Caught exception which should be unwrapped. ''' Message which will be appended to the unwrapped exception. Public Sub ThrowIfCausedCancelOf(ex As OperationCanceledException, Optional message As String = Nothing) If ex.CancellationToken = Me.Token Then Me.ThrowIfAnyCancellationRequested(ex, message) End If End Sub ''' ''' Throws if any of contained tokens has had ''' cancellation requested. ''' Public Sub ThrowIfCancellationRequested() Me.ThrowIfCancellationRequested(Nothing, Nothing) End Sub ''' ''' Throws if any of contained tokens has had ''' cancellation requested. ''' Public Sub ThrowIfCancellationRequested(message As String) Me.ThrowIfCancellationRequested(Nothing, message) End Sub ''' ''' Throws if any of contained tokens has had ''' cancellation requested. ''' Public Sub ThrowIfCancellationRequested(ex As Exception, Optional message As String = Nothing) For i = 0 To Me.tokens.Length - 1 If Me.tokens(i).IsCancellationRequested Then Throw New OperationCanceledException(message, ex, Me.tokens(i)) End If Next End Sub Public Shared Function Create(token1 As CancellationToken, token2 As CancellationToken) As LinkedCancellationTokenSource Dim internalSource = CancellationTokenSource.CreateLinkedTokenSource(token1, token2) Return New LinkedCancellationTokenSource(internalSource, {token1, token2}) End Function Public Shared Function Create(ParamArray tokens As CancellationToken()) As LinkedCancellationTokenSource Dim internalSource = CancellationTokenSource.CreateLinkedTokenSource(tokens) Return New LinkedCancellationTokenSource(internalSource, tokens) End Function #Region "IDisposable Support" Private disposedValue As Boolean ' To detect redundant calls ' IDisposable Protected Overridable Sub Dispose(disposing As Boolean) If Not Me.disposedValue Then If disposing Then ' dispose managed state (managed objects). Me.internalSource.Dispose() End If ' free unmanaged resources (unmanaged objects) and override Finalize() below. ' set large fields to null. End If Me.disposedValue = True End Sub ' override Finalize() only if Dispose(ByVal disposing As Boolean) above has code to free unmanaged resources. 'Protected Overrides Sub Finalize() ' ' Do not change this code. Put cleanup code in Dispose(ByVal disposing As Boolean) above. ' Dispose(False) ' MyBase.Finalize() 'End Sub ' This code added by Visual Basic to correctly implement the disposable pattern. Public Sub Dispose() Implements IDisposable.Dispose ' Do not change this code. Put cleanup code in Dispose(disposing As Boolean) above. Dispose(True) GC.SuppressFinalize(Me) End Sub #End Region End Class End Namespace
上述示例中的用法:
Using linkedCts = LinkedCancellationTokenSource.Create(externalCancelToken, internalCancelToken) Try myRequest.Dispatch(linkedCts.Token) Catch ex As WebException When ex.Status = WebExceptionStatus.RequestCanceled linkedCts.ThrowIfCancellationRequested(ex) Throw Catch ex As OperationCanceledException linkedCts.ThrowIfCausedCancelOf(ex) Throw End Try End Using
请向上/向下投票决定这是好还是坏的解决方案。此外,欢迎更好地命名方法的想法。