Skip to content

阻止线程上下文的流动

🏷️ C# 学习

执行上下文的流动使得程序的执行效率下降很多,线程上下文的包装是一个成本较高的工作,而有时这样的包装并不是必需的。

这种情况下,程序员就需要手动地防止线程上下文的流动,常用的有下面两种方法:

  • 使用定义在 System.Threading.ThreadPool 类型中的 UnsafeQueueUserWorkItem 方法

  • 使用定义在 ExecutionContext 类型中的 SuppressFlow 方法

示例代码

点击查看代码
cs
using System;
using System.IO;
using System.Security;
using System.Security.Permissions;
using System.Threading;

namespace SuppressContextFlow
{
    class Program
    {
        private static string _testFIle = "D:\\TestContext.txt";

        static void Main(string[] args)
        {
            try
            {
                // 建立测试文件
                CreateTestFile();

                // 现在修改安全上下文
                // 阻止文件访问
                FileIOPermission fip = new FileIOPermission(FileIOPermissionAccess.AllAccess, _testFIle);
                fip.Deny();
                Console.WriteLine("已阻止文件访问");

                // 测试当前线程安全上下文
                Console.Write("主线程权限测试:");
                TestPermission(null);
                // 建立一个子线程
                Console.Write("子线程权限测试:");
                // 使用 UnsafeQueueUserWorkItem 方法
                ThreadPool.UnsafeQueueUserWorkItem(TestPermission, null);
                Thread.Sleep(1000);

                // 使用 SuppressFlow 方法
                using (AsyncFlowControl afc = ExecutionContext.SuppressFlow())
                {
                    Console.Write("主线程权限测试:");
                    TestPermission(null);
                    // 建立一个子线程
                    Console.Write("子线程权限测试:");
                    Thread son1 = new Thread(TestPermission);
                    son1.Start();
                    son1.Join();
                }

                // 现在修改安全上下文
                // 恢复文件访问
                SecurityPermission.RevertDeny();
                Console.WriteLine("已恢复文件访问");

                // 测试当前线程安全上下文
                Console.Write("主线程权限测试:");
                TestPermission(null);
                // 建立一个子线程
                Console.Write("子线程权限测试:");
                Thread son2 = new Thread(TestPermission);
                son2.Start();
                son2.Join();

                Console.Read();
            }
            finally
            {
                // 删除测试文件
                DeleteTesfFile();
            }
        }

        /// <summary>
        /// 建立测试文件
        /// </summary>
        static void CreateTestFile()
        {
            if (!File.Exists(_testFIle))
            {
                using (FileStream fs = File.Create(_testFIle))
                {

                }
            }
        }

        /// <summary>
        /// 删除测试文件
        /// </summary>
        private static void DeleteTesfFile()
        {
            try
            {
                if (File.Exists(_testFIle))
                {
                    File.Delete(_testFIle);
                }
            }
            catch (Exception)
            {

                throw;
            }
        }

        /// <summary>
        /// 尝试访问文件来测试安全上下文
        /// </summary>
        /// <param name="state"></param>
        private static void TestPermission(object state)
        {
            try
            {
                // 尝试访问文件
                File.GetCreationTime(_testFIle);
                // 如果没有异常则测试通过
                Console.WriteLine("权限测试通过");
            }
            catch (SecurityException)
            {
                // 表明没有权限访问
                Console.WriteLine("权限测试没有通过");
            }
        }
    }
}

输出结果

点击查看输出结果
已阻止文件访问
主线程权限测试:权限测试没有通过
子线程权限测试:权限测试通过
主线程权限测试:权限测试没有通过
子线程权限测试:权限测试通过
已恢复文件访问
主线程权限测试:权限测试通过
子线程权限测试:权限测试通过

注意

阻止线程执行上下文的流动会潜在的提高子线程的安全权限,这是因为主线程中的安全限制没有附件到子线程之上。

在设计的时候应充分考虑到这个问题,在保证不影响到系统安全性的前提下再着手提高效率。