如何让默认的CancellationToken与对应的CancellationTokenSource关联?

12
当我创建一个默认的CancellationToken时,我可以在调试器中看到CancellationToken与其关联的CancellationTokenSource,它存储在私有的m_source字段中。

Not null

我想知道对于结构体来说,default关键字"将返回结构体的每个成员初始化为零或null,具体取决于它们是值类型还是引用类型",而CancellationTokenSource是引用类型,这怎么可能呢? CancellationToken有两个构造函数可以设置该字段,但它们都不相关,因为default(CancellationToken)不调用构造函数,new CancellationToken()(具有完全相同的行为)不调用构造函数,因为结构体不能有无参构造函数(尚未)。
1个回答

16

default(CancellationToken) 方法会创建一个 CancellationToken 对象,m_source 属性的值为 null。您可以通过使用反射获取该私有字段的值来查看它:

Console.WriteLine(typeof (CancellationToken).
    GetField("m_source", BindingFlags.NonPublic | BindingFlags.Instance).
    GetValue(default(CancellationToken)) ?? "null");

输出:

null

您还可以通过仅在调试器中固定相关字段来查看:

null

那么会发生什么呢?

调试器为了显示 CancellationToken 的内容,逐个访问其属性。当内部的 CancellationTokenSourcenull 时,WaitHandle 属性会创建并设置一个默认的 CancellationTokenSource,然后委托给它的 WaitHandle 属性:

public WaitHandle WaitHandle
{
    get
    {
        if (m_source == null)
        {
             m_source = CancellationTokenSource.InternalGetStaticSource(false);
        }

        return m_source.WaitHandle;
    }
}

总之,default(CancellationToken)new CancellationToken 创建一个空结构体,其中m_sourcenull,但是在调试器中查看结构体时,你正在填充该字段,用默认的CancellationTokenSource实例,该实例无法取消。


1
.NET 的“量子式”特性非常明显。 - Pona

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