partial class Program { 完成异步操作后的回调方法 FinshCallBack(IAsyncResult result) { ReadFileClass rfc = result.AsyncState as ReadFileClass; if (rfc != null) { length = rfc.stream.EndRead(result); [] fileData = new byte[length]; Array.Copy(rfc.data, 0, fileData, 0, fileData.Length); string content = Encoding.UTF8.GetString(fileData); // 打印读取到的文件基本信息 Console.WriteLine(, length.ToString(), content); } } }
View Code③ 定义了作为状态对象传递的类型,这个类型对所有需要传递的数据包进行打包:
传递给异步操作的回调方法 ReadFileClass { FileStream stream; [] data; public ReadFileClass(FileStream stream,byte[] data) { this.stream = stream; this.data = data; } }
View Code下图展示了该实例的执行结果:
如上面的实例,使用回调方法的异步模式需要花费一点额外的代码量,因为它需要将异步操作的对象及操作的结果数据都打包到一个类型里以便能够传递回给回调的委托方法,这样在委托方法中才能够有机会处理操作的结果,并且调用EndXXX方法以释放资源。
2.6 如何阻止线程执行上下文的传递?(1)何为线程的执行上下文
在.NET中,每一个线程都会包含一个执行上下文,执行上下文是指线程运行中某时刻的上下文概念,类似于一个动态过程的快照(SnapShot)。在.NET中,System.Threading中的ExecutionContext类型代表了一个执行上下文,该执行上下文会包含:安全上下文、调用上下文、本地化上下文、事务上下文和CLR宿主上下文等等。通常情况下,我们将所有这些综合成为线程的上下文。
(2)执行上下文的流动
当程序中新建一个线程时,执行上下文会自动地从当前线程流入到新建的线程之中,这样做可以保证新建的线程天生就就有和主线程相同的安全设置和文化等设置。下面的示例代码通过修改安全上下文来展示线程上下文的流动性,主要使用到ExecutionContext类的Capture方法来捕获当前想成的执行上下文。
① 首先定义一些辅助犯法,封装了文件的创建、删除和文件访问权限检查:
partial class Program { CreateTestFile() { if (!File.Exists(testFile)) { FileStream stream = File.Create(testFile); stream.Dispose(); } } DeleteTestFile() { if (File.Exists(testFile)) { File.Delete(testFile); } } JudgePermission(object state) { try { // 尝试访问文件 File.GetCreationTime(testFile); // 如果没有异常则测试通过 Console.WriteLine(); } catch (SecurityException) { // 如果出现异常则测试通过 Console.WriteLine(); } finally { Console.WriteLine(); } } }
View Code② 其次在入口方法中使主线程和创建的子线程访问指定文件来查看权限上下文流动到子线程中的情况:(这里需要注意的是由于在.NET 4.0及以上版本中FileIOPermission的Deny方法已过时,为了方便测试,将程序的.NET版本调整为了3.5)
partial class Program { testFile = ; static void Main(string[] args) { try { CreateTestFile(); // 测试当前线程的安全上下文 Console.WriteLine(); JudgePermission(null); // 创建一个子线程 subThread1 Console.WriteLine(); Thread subThread1 = new Thread(JudgePermission); subThread1.Start(); subThread1.Join(); // 现在修改安全上下文,阻止文件访问 FileIOPermission fip = new FileIOPermission(FileIOPermissionAccess.AllAccess, testFile); fip.Deny(); Console.WriteLine(); // 测试当前线程的安全上下文 Console.WriteLine(); JudgePermission(null); // 创建一个子线程 subThread2 Console.WriteLine(); Thread subThread2 = new Thread(JudgePermission); subThread2.Start(); subThread2.Join(); // 现在修改安全上下文,允许文件访问 SecurityPermission.RevertDeny(); Console.WriteLine(); // 测试当前线程安全上下文 Console.WriteLine(); JudgePermission(null); // 创建一个子线程 subThread3 Console.WriteLine(); Thread subThread3 = new Thread(JudgePermission); subThread3.Start(); subThread3.Join(); Console.ReadKey(); } finally { DeleteTestFile(); } } }
View Code该实例的执行结果如下图所示,从图中可以看出程序中通过FileIOPermission对象来控制对主线程对文件的访问权限,并且通过新建子线程来查看主线程的安全上下文的改变是否会影响到子线程。
正如刚刚说到,主线程的安全上下文将作为执行上下文的一部分由主线程传递给子线程。
(3)阻止上下文的流动