第十章(2)-等待异步调用的完成-学习笔记

使用轮询:

我们对上一节的内容进行改进,让计算机每隔100ms向控制台输出一个小点(.)。运用了IAsyncResult接口的属性:

using System;
using System.Collections.Generic;
using System.Text;
using System.IO;
using System.Threading;

namespace CalculateFolderSizeNoAsync
{
    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 CalculateFolderSizeD(string FolderName);
        static void Main(string[] args)
        {
            long size;
            string FolderName;
            CalculateFolderSizeD d = CalculateFolderSize; 
            Console.WriteLine("请输入文件夹名称(例如:C:\\Windows):");
            FolderName = Console.ReadLine();
            //通过委托异步调用静态方法CalculateFolderSize
            IAsyncResult ret = d.BeginInvoke(FolderName, null, null);
            Console.Write("正在计算中,请耐心等待");
            //阻塞,等到调用完成,取出结果
            while (ret.IsCompleted==false)
            {
                Console.Write(".");
                Thread.Sleep(100);
            }
            Console.WriteLine();
            size = d.EndInvoke(ret);
            //size = CalculateFolderSize(FolderName);//不用这个了
            Console.WriteLine("\n文件夹{0}的容量为:{1}字节\n", FolderName, size);
            Console.ReadKey();


            

        }
    }
}
使用“等待句柄”实现同样的功能:

using System;
using System.Collections.Generic;
using System.Text;
using System.IO;
using System.Threading;

namespace CalculateFolderSizeNoAsync
{
    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 CalculateFolderSizeD(string FolderName);
        static void Main(string[] args)
        {
            long size;
            string FolderName;
            CalculateFolderSizeD d = CalculateFolderSize; 
            Console.WriteLine("请输入文件夹名称(例如:C:\\Windows):");
            FolderName = Console.ReadLine();
            //通过委托异步调用静态方法CalculateFolderSize
            IAsyncResult ret = d.BeginInvoke(FolderName, null, null);
            Console.Write("正在计算中,请耐心等待");
            //阻塞,等到调用完成,取出结果
            while(!ret.AsyncWaitHandle.WaitOne(100))//使用等待句柄
            {
                //等待2秒钟,输出一个“.”
                Console.Write(".");
            }
            Console.WriteLine();
            size = d.EndInvoke(ret);
            //size = CalculateFolderSize(FolderName);//不用这个了
            Console.WriteLine("\n文件夹{0}的容量为:{1}字节\n", FolderName, size);
            Console.ReadKey();


            

        }
    }
}
前面的两个例子中,使用轮询的方式不断地询问异步调用是否完成?这一方法无疑会在循环等待上浪费不少cpu时间。能不能让异步调用的方法在结束时自动调用一个方法,并在方法中显示处理结果?

使用异步回调满足要求:

using System;
using System.Collections.Generic;
using System.Text;
using System.IO;
using System.Threading;

namespace CalculateFolderSizeNoAsync
{
    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 CalculateFolderSizeD(string FolderName);

        private static CalculateFolderSizeD d = CalculateFolderSize;

        public static void ShowFolderSize(IAsyncResult result)//定义一个供异步调用回调的方法
        {
            long size = d.EndInvoke(result);
            Console.WriteLine("{0}是{1}字节",(string)result.AsyncState,size);
        }
        static void Main(string[] args)
        {
            string foldername;
            while (true)
            {
                Console.WriteLine("input like this:C:\\Windows");
                foldername = Console.ReadLine();
                d.BeginInvoke(foldername,ShowFolderSize,foldername);
            }

        }
    }
}
BeginInvoke方法定义中的最后两个参数“AsyncCallback callback”和“object asyncState”就是用来异步调用的。

注意:BeginInvoke方法的第二个参数指定当异步调用结束时回调ShowFolderSize方法,第三个参数asyncState被填入要计算的文件夹的名字,此值被BeginInvoke方法包装到自动创建的一个IAsyncResult类型的对象中,并作为方法实参自动传送给回调方法(本例中回调方法ShowFolderSize的参数result),回调方法通过这一参数的AsyncState字段获取其值。其中第三个参数是object类型,所以可以是任意的类型。所以当回调的参数的数量不只是一个时(如果有多个信息需要传送给回调方法时),可以将所有要传送的信息封装到一个struct变量,或者干脆再定义一个类。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值