24

我正在阅读和学习有关ThreadScheduler任务的文章,并遇到了ThreadPool.UnsafeQueueUserWorkItem一个MSDN 示例中使用的有关自己的 ThreadScheduler 的函数。在关于 UnsafeQueueUserWorkItem的 MSDN描述中,有一个很大的警告,该函数可能是一个安全漏洞,并且它“不会传播调用堆栈”。

唯一的链接是QueueUserWorkItem哪个——从名字上看——似乎是“安全对应物”?但也没有提到任何关于调用堆栈的内容。

传播堆栈到底意味着什么?在工作开始之前复制它?为什么另一个线程仍然需要调用线程的堆栈?我会假设他们从一个新的空堆栈开始。毕竟线程函数返回的时候,不会继续执行调度Task的函数吧?

4

1 回答 1

30

它是 CAS(代码访问安全性)的实现细节。它可以检查一个线程是否有足够的权限来执行一个操作。仅当代码在受限制的安全环境中运行,而不是在完全信任的情况下或在沙箱中运行时才重要。

完成这项工作的管道很复杂,我只能近似它的工作方式。ExecutionContext 类是关键,它确定代码运行的安全上下文。当以受限权限运行的线程启动另一个线程时,事情会变得很困难。显然,其他线程需要在与原始线程相同的限制下运行。CAS 依赖于能够执行堆栈遍历以发现限制。这在另一个线程上很困难,它有自己的堆栈。

ExecutionContext.Capture() 方法在这里发挥着重要作用。它复制调用线程的上下文,包括进行堆栈遍历以创建已发现的安全属性的“压缩”堆栈。然后新线程使用捕获的上下文运行。

ThreadPool.UnsafeQueueUserWorkItem() 跳过 Capture() 调用。线程池线程将使用默认执行上下文运行。

这是一种优化,Capture() 不是一种便宜的方法。对于依赖 TP 线程快速完成任务的程序来说,这很重要。一个网络服务器跳到脑海中。也是使用该方法的代码类型,例如,您可以在 System.Net 命名空间的内部方法中看到它。

显然它是不安全的,它不能在原始线程的 CAS 限制下运行。

于 2013-06-04T22:49:46.663 回答