第十章(3)-异步调用中的异常与任务同步-学习笔记
2016-01-05 10:29
387 查看
同步编程中的异常处理由try和catch,同样异步编程时,异步调用的方法抛出一个异常时,CLR会捕捉他,当调用者线程(启动异步调用的线程)调用EndInvoke时,CLR会再次将异常抛出,这样调用者线程可捕获到她。如果BeginInvoke方法提供了一个回调方法,则CLR会在捕获异常后马上调用回调方法,并将异常传送给调用者线程。由此得出结论:
请在EndInvoke方法所在的代码处捕获异常(使用try和catch)。
用一个例子说明这一概念其实很容易理解的。我们运行上面的代码,由于存在多个同时进行的异步调用,会出现下面的问题:
例如:用户输入文件夹名“C:\EBook”,然后,他想输入另一个文件夹名“C:\Mybook”,但是他刚输入到“C:\My”时前一项工作已完成控制台窗口输出“文件夹C:\EBook的容量为:770774156字节”,总之输入被打断,但是用户接着完成输入“book”,程序也是可以完成任务的。
但是用户不想有这种体验,这就涉及到“异步调用任务中的同步”。可以这样解决上面的问题:
请在EndInvoke方法所在的代码处捕获异常(使用try和catch)。
using System; using System.Collections.Generic; using System.Text; using System.IO; namespace AsyncCalculateFolderSize5 { class Program { //计算指定文件夹的总容量 private static long CalculateFolderSize(string FolderName) { if (Directory.Exists(FolderName) == false) { throw new DirectoryNotFoundException("文件夹不存在"); } DirectoryInfo RootDir = new DirectoryInfo(FolderName); //获取所有的子文件夹 DirectoryInfo[] ChildDirs = RootDir.GetDirectories(); //获取当前文件夹中的所有文件 FileInfo[] files = RootDir.GetFiles(); long totalSize = 0; //累加每个文件的大小 foreach (FileInfo file in files) { totalSize += file.Length; } //对每个文件夹执行同样的计算过程:累加其下每个文件的大小 //这是通过递归调用实现的 foreach (DirectoryInfo dir in ChildDirs) { totalSize += CalculateFolderSize(dir.FullName); } //返回文件夹的总容量 return totalSize; } //定义一个委托 public delegate long CalculateFolderSizeDelegate(string FolderName); private static CalculateFolderSizeDelegate d = new CalculateFolderSizeDelegate(CalculateFolderSize); //用于回调的函数 public static void ShowFolderSize(IAsyncResult result) { try { long size = d.EndInvoke(result); Console.WriteLine("\n文件夹{0}的容量为:{1}字节\n", (String)result.AsyncState, size); } catch (DirectoryNotFoundException e) { Console.WriteLine("您输入的文件夹不存在"); } } static void Main(string[] args) { string FolderName; while (true) { Console.WriteLine("请输入文件夹名称(例如:C:\\Windows),输入quit结束程序"); FolderName = Console.ReadLine(); if (FolderName == "quit") break; d.BeginInvoke(FolderName, ShowFolderSize, FolderName); } } } }实现异步调用任务中的同步:
用一个例子说明这一概念其实很容易理解的。我们运行上面的代码,由于存在多个同时进行的异步调用,会出现下面的问题:
例如:用户输入文件夹名“C:\EBook”,然后,他想输入另一个文件夹名“C:\Mybook”,但是他刚输入到“C:\My”时前一项工作已完成控制台窗口输出“文件夹C:\EBook的容量为:770774156字节”,总之输入被打断,但是用户接着完成输入“book”,程序也是可以完成任务的。
但是用户不想有这种体验,这就涉及到“异步调用任务中的同步”。可以这样解决上面的问题:
using System; using System.Collections.Generic; using System.Text; using System.IO; namespace AsyncCalculateFolderSize6 { class Program { //计算指定文件夹的总容量 private static long CalculateFolderSize(string FolderName) { if (Directory.Exists(FolderName) == false) { throw new DirectoryNotFoundException("文件夹不存在"); } DirectoryInfo RootDir = new DirectoryInfo(FolderName); //获取所有的子文件夹 DirectoryInfo[] ChildDirs = RootDir.GetDirectories(); //获取当前文件夹中的所有文件 FileInfo[] files = RootDir.GetFiles(); long totalSize = 0; //累加每个文件的大小 foreach (FileInfo file in files) { totalSize += file.Length; } //对每个文件夹执行同样的计算过程:累加其下每个文件的大小 //这是通过递归调用实现的 foreach (DirectoryInfo dir in ChildDirs) { totalSize += CalculateFolderSize(dir.FullName); } //返回文件夹的总容量 return totalSize; } //定义一个委托 public delegate long CalculateFolderSizeDelegate(string FolderName); private static CalculateFolderSizeDelegate d = new CalculateFolderSizeDelegate(CalculateFolderSize); //用于回调的函数 public static void ShowFolderSize(IAsyncResult result) { try { long size = d.EndInvoke(result); while (Console.CursorLeft != 0) { //等待2秒 System.Threading.Thread.Sleep(2000); } Console.WriteLine("\n文件夹{0}的容量为:{1}字节\n", (String)result.AsyncState, size); } catch (DirectoryNotFoundException e) { Console.WriteLine("您输入的文件夹不存在"); } } static void Main(string[] args) { string FolderName; while (true) { Console.WriteLine("请输入文件夹名称(例如:C:\\Windows),输入quit结束程序"); FolderName = Console.ReadLine(); if (FolderName == "quit") break; d.BeginInvoke(FolderName, ShowFolderSize, FolderName); } } } }控制台窗口的坐标是以字符为单位的,当用户输入时,光标X轴方向的坐标会不断增大,由此判断用户是否在输入。
相关文章推荐
- selenium让人摸不着头脑的问题
- Android中selector背景选择器
- Android Studio之导入外部so库
- 26个复古风格网站设计欣赏
- kendoGrid选中行信息
- JAVA学习【1】书写与命名规则
- POJ 1321 - 棋盘问题
- spark源码阅读3-Task运行期之函数调用关系分析
- Leetcode----292.Nim Game(easy)
- 支付相关开发
- RMI(远程接口调用)
- node.js+express+mysql
- Android View之组合控件实例(一)
- 页面加载时间过长
- Android4.4 RIL的AT命令增加流程
- 视频传输Bitmap数据
- 心情不好吗?来看看让你满血复活
- 页面加载时间过长
- 2015年工作总结
- nginx配置文件讲解