我可以使用 cancellationToken == CancellationToken.None 来检查 default(CancellationToken) 吗?

6
原因在于如果是CancellationToken.None的话,我需要添加一个超时时间(因此需要来自CancellationTokenSource的新CancellationToken),例如:
if (cancellationToken == CancellationToken.None)
{
    var tokenSource = new CancellationTokenSource();
    tokenSource.CancelAfter((int)_timeout.TotalMilliseconds);

    cancellationToken = tokenSource.Token;
}

另一个想法是创建一个组合令牌。
更新。这样的做法是否可行?我需要注意哪些问题?垃圾回收是否会按需执行?
public async Task<int> InternalActionAsync(CancellationToken token)
{
    // do something with the token...
    return 1;
}

public Task<int> ExternalActionAsync(CancellationToken token = default(CancellationToken))
{
    var internalTokenSource = 
            new CancellationTokenSource((int)_timeout.TotalMilliseconds);
    var linkedTokenSource = 
            CancellationTokenSource.CreateLinkedTokenSource(token, 
                                                            internalTokenSource.Token);

    return InternalActionAsync(linkedTokenSource.Token);
}

我认为这样做可能有效,但似乎有些奇怪,因为用户尚未发起取消操作,但任务已被取消。 - NeddySpaghetti
没错。我正在尝试添加一个超时功能,这在Windows.Web.Http.HttpClient中与System.Net HttpClient相比是缺失的。 - tofutim
Console.WriteLine(default(System.Threading.CancellationToken) == System.Threading.CancellationToken.None); 输出结果为 "True"。 - Special Sauce
2个回答

7

首先,查看源代码

public static CancellationToken None
{
    get { return default(CancellationToken); }
}

所以,你可以安全地假设它们是相等的。

但是,如果用户没有传递 CancellationToken,也许你可以请求一个 CancellationToken?,而不是依赖于默认的令牌相等性:

public Task<int> ExternalActionAsync(CancellationToken? token = null)
{
    if (token == null)
    {
        var tokenSource = new CancellationTokenSource();
        tokenSource.CancelAfter((int)_timeout.TotalMilliseconds);
        token = tokenSource.Token;
    }

    return InternalActionAsync(token);
}

1
你可以将 CancellationToken 的默认值与 CancellationToken.None 进行比较,结果将是 true。默认的 CancellationToken 没有令牌源,CancellationToken.None 也返回默认值。当您比较这两个值时,比较会发现两个值都没有令牌源,并将它们视为相等。 CancellationToken 是值类型,唯一的 GC 问题可能是引用的令牌源,但默认取消令牌没有令牌源。
关于您的第二个解决方案,在默认取消令牌的情况下,它不会真正地将它们链接起来,它将忽略默认令牌(没有令牌源,因此无法订阅其取消)。我看不到这个解决方案存在任何问题。

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接