【问题标题】:Best practice how to unwrap CancellationToken when using linked CancellationTokenSource使用链接的 CancellationTokenSource 时如何解开 CancellationToken 的最佳实践
【发布时间】:2014-06-05 11:09:33
【问题描述】:

我目前在我的应用程序中采用.NET Cancellation Framework。看来我需要时不时地使用链接的CancellationTokenSource,并且我发现在每个匹配的捕获中“解包”OperationCanceledException 以便它包含正确的CancellationToken 很乏味。我想问一下:

  1. 是否有任何开箱即用的解决方案来促进这种情况?
  2. 什么是处理它的“最佳实践”?

我的问题是关于 .NET 4。我还附上了代码示例,它显示了我在说什么:

使用linkedCts = CancellationTokenSource.CreateLinkedTokenSource(externalCancelToken, internalCancelToken) 尝试 myRequest.Dispatch(linkedCts.Token) 当 ex.Status = WebExceptionStatus.RequestCanceled 时将 ex 作为 WebException 捕获 If externalCancelToken.IsCancellationRequested Then 抛出新的 OperationCanceledException(externalCancelToken) ElseIf internalCancelToken.IsCancellationRequested Then 抛出新的 OperationCanceledException(internalCancelToken) 别的 扔 万一 捕获前作为 OperationCanceledException 如果 ex.CancellationToken = linkedCts.Token 那么 If externalCancelToken.IsCancellationRequested Then 抛出新的 OperationCanceledException(无,例如,externalCancelToken) ElseIf internalCancelToken.IsCancellationRequested Then 抛出新的 OperationCanceledException(Nothing, ex, internalCancelToken) 万一 万一 结束尝试 结束使用

【问题讨论】:

    标签: .net vb.net cancellation


    【解决方案1】:

    我试图用谷歌搜索一些想法,但一无所获。所以我想出了以下链接 CancellationTokenSource-es 的包装器:

    导入 System.Threading 命名空间线程 公共类 LinkedCancellationTokenSource 实现 IDisposable 公共只读属性令牌作为 CancellationToken 得到 返回 Me.internalSource.Token 结束获取 结束属性 公共只读属性 IsCancellationRequested 作为布尔值 得到 返回 Me.internalSource.IsCancellationRequested 结束获取 结束属性 私有只读令牌作为 CancellationToken() Private ReadOnly internalSource 作为 CancellationTokenSource Private Sub New(internalSource As CancellationTokenSource, tokens As CancellationToken()) Me.internalSource = internalSource Me.tokens = 代币 结束子 公共子取消() Me.internalSource.Cancel() 结束子 ''' ''' 尝试解开任何包含的内容 ''' 在这个来源。如果异常中的令牌未知, ''' 什么都不会被抛出,你必须提升。 ''' ''' 捕获的异常应该被解包。 ''' 将附加到解包异常的消息。 Public Sub ThrowIfCausedCancelOf(ex As OperationCanceledException, Optional message As String = Nothing) 如果 ex.CancellationToken = Me.Token 那么 Me.ThrowIfAnyCancellationRequested(例如,消息) 万一 结束子 ''' ''' 如果任何包含的标记有 ''' 请求取消。 ''' 公共子 ThrowIfCancellationRequested() Me.ThrowIfCancellationRequested(无,无) 结束子 ''' ''' 如果任何包含的标记有 ''' 请求取消。 ''' 公共子 ThrowIfCancellationRequested(消息作为字符串) Me.ThrowIfCancellationRequested(无,消息) 结束子 ''' ''' 如果任何包含的标记有 ''' 请求取消。 ''' 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 抛出新的 OperationCanceledException(消息,例如,Me.tokens(i)) 万一 下一个 结束子 公共共享函数 Create(token1 As CancellationToken, token2 As CancellationToken) As LinkedCancellationTokenSource 暗淡 internalSource = CancellationTokenSource.CreateLinkedTokenSource(token1, token2) 返回新的 LinkedCancellationTokenSource(internalSource, {token1, token2}) 结束功能 公共共享函数 Create(ParamArray tokens As CancellationToken()) As LinkedCancellationTokenSource 暗淡 internalSource = CancellationTokenSource.CreateLinkedTokenSource(tokens) 返回新的 LinkedCancellationTokenSource(internalSource, tokens) 结束功能 #Region “IDisposable 支持” Private DisposedValue As Boolean ' 检测冗余调用 ' 一次性 受保护的可覆盖子处置(处置为布尔值) If Not Me.disposedValue Then 如果处置 那么 ' 处置托管状态(托管对象)。 我.internalSource.Dispose() 万一 ' 释放非托管资源(非托管对象)并覆盖下面的 Finalize()。 ' 将大字段设置为空。 万一 Me.disposedValue = True 结束子 ' 仅当上面的 Dispose(ByVal disposing As Boolean) 具有释放非托管资源的代码时才覆盖 Finalize()。 '受保护的覆盖 Sub Finalize() ' ' 不要更改此代码。将清理代码放在上面的 Dispose(ByVal disposing As Boolean) 中。 ' 处置(假) ' MyBase.Finalize() '结束子 ' 此代码由 Visual Basic 添加以正确实现一次性模式。 Public Sub Dispose() 实现 IDisposable.Dispose ' 不要更改此代码。将清理代码放在上面的 Dispose(disposing As Boolean) 中。 处置(真) GC.SuppressFinalize(Me) 结束子 #结束区域 结束类 结束命名空间

    在上述例子中的用法:

    使用linkedCts = LinkedCancellationTokenSource.Create(externalCancelToken, internalCancelToken) 尝试 myRequest.Dispatch(linkedCts.Token) 当 ex.Status = WebExceptionStatus.RequestCanceled 时将 ex 作为 WebException 捕获 linkedCts.ThrowIfCancellationRequested(ex) 扔 捕获 ex 作为 OperationCanceledException linkedCts.ThrowIfCausedCancelOf(ex) 扔 结束尝试 结束使用

    请投票赞成/反对这是好的还是坏的解决方案。也欢迎更好地命名方法的想法。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2012-03-18
      • 1970-01-01
      • 2010-09-17
      • 2011-08-10
      • 2010-12-16
      相关资源
      最近更新 更多