如果我在取消CancellationToken
之前注册了一些回调,则似乎在取消令牌时会以相反的顺序调用它们。这样的调用顺序可以保证吗?
var cts = new CancellationTokenSource();
var token = cts.Token;
token.Register(() => Console.WriteLine("1"));
token.Register(() => Console.WriteLine("2"));
token.Register(() => Console.WriteLine("3"));
cts.Cancel();
这将输出
3
2
1
答案 0 :(得分:4)
好吧,在CancellationToken类的source code中,情况似乎是如此。方法ExecuteCallbackHandlers(bool throwOnFirstException)
负责获取并执行回调。它包含以下代码片段:
try
{
for (int index = 0; index < callbackLists.Length; index++)
{
SparselyPopulatedArray<CancellationCallbackInfo> list = Volatile.Read<SparselyPopulatedArray<CancellationCallbackInfo>>(ref callbackLists[index]);
if (list != null)
{
SparselyPopulatedArrayFragment<CancellationCallbackInfo> currArrayFragment = list.Tail;
while (currArrayFragment != null)
{
for (int i = currArrayFragment.Length - 1; i >= 0; i--)
{
... some other code
}
}
}
}
}
在内部for
循环中,它从最后一个元素向后一个元素遍历回调数组的片段。
但是,如@Nick所述,不能在文档中保证。一个简单的解决方案是将回调添加到一个委托中-这样,我们就可以更好地控制执行顺序:
token.Register(() =>
{
Console.WriteLine("1"));
Console.WriteLine("2"));
Console.WriteLine("3"));
});