[C#学习笔记之异步编程模式1]了解同步与异步

同步执行

程序执行的流程是按照语句顺序执行,一句执行完再执行下一句,如果遇到函数调用,要等到函数调用返回以后才会执行下一句——这就是“程序的同步执行模式”。

例 1:

using System.Threading;
using System;

public class SynchroPattern
{
    public delegate int NewTaskDelegate(int x);

    public static int NewTask(int x)
    {
        Thread.Sleep(5000);//此处模拟长时间执行的任务
        return x + x;
    }
    public static void Main(string[] args)
    {
        NewTaskDelegate task = NewTask;

        //同步执行
        int syncResult = task(10);
        Console.WriteLine("Sync Proccessing operation...");//这一行只有SyncMethod完成以后才能显示
        Console.WriteLine("Sync Result is: {0}", syncResult);
    }
}

当程序执行到 int syncResult = task(10); 的时候,主线程将等待至少5秒的时间(NewTask方法的执行),才能执行后面的代码,也即在期间,应用程序没有响应,不能执行其他的任何操作,直到NewTask方法返回结果。


例 2:

计算输入的文件夹的容量

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

namespace CalculateFolderSizeNoAsync
{
    class Program
    {
        //定义一个委托
        public delegate long CalculateFolderSizeDelegate(string FolderName);

        //计算指定文件夹的总容量
        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;
        }

        static void Main(string[] args)
        {
            long size;
            string FolderName;
            CalculateFolderSizeDelegate task = CalculateFolderSize;
            Console.WriteLine("请输入文件夹名称(例如:C:\\Windows):");
            FolderName = Console.ReadLine();                          
            size = task(FolderName);
            Console.WriteLine("\n文件夹{0}的容量为:{1}字节", FolderName , size);
        }
    }
}
同样,在CalculateFolderSize执行结束之前,无法执行其后的任何语句!

异步执行

如果计算机在调用函数时,并不需要函数调用结束就继续执行后面的语句,而采用回调的方式处理函数调用,计算机就进入了“程序的异步调用模式”。

我们对例1进行稍微的修改:

using System.Threading;
using System;

public class AsynchroPattern
{
    public delegate int NewTaskDelegate(int x);

    public static int NewTask(int x)
    {
        Thread.Sleep(5000);//此处模拟长时间执行的任务
        return x + x;
    }
    public static void Main(string[] args)
    {
        NewTaskDelegate task = NewTask;
        //通过委托异步调用静态方法NewTask,不是在当前线程调用,而是在另外一个线程调用
        IAsyncResult ret = task.BeginInvoke(10, null, null);
        Console.WriteLine("正在计算中,请耐心等待……"); //即使NewTask方法没有执行结束本行语句也会执行
        int syncResult = task.EndInvoke(ret);  //阻塞,等到调用完成,取出结果
        Console.WriteLine("Sync Result is: {0}", syncResult);
    }
}
注意: 

1.当使用BeginInvoke异步调用方法时,如果方法未执行完,EndInvoke方法就会一直阻塞,直到被调用的方法执行完毕。

2.在运行上面的程序后,由于newTask方法通过Sleep延迟了5秒,因此,程序直到5秒后才输出最终结果x+x。如果不调用EndInvoke方法,程序会立即退出,这是由于使用BeginInvoke创建的线程都是后台线程,这种线程一但所有的前台线程都退出后(其中主线程就是一个前台线程),不管后台线程是否执行完毕,都会结束线程,并退出程序。

同样,对例2修改后的异步执行代码:

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


namespace AsyncCalculateFolderSize1
{
    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);

        static void Main(string[] args)
        {

            //定义一个委托变量引用静态方法CalculateFolderSize
            CalculateFolderSizeDelegate d = CalculateFolderSize;
           
            Console.WriteLine("请输入文件夹名称(例如:C:\\Windows):");

            string FolderName = Console.ReadLine();

            //通过委托异步调用静态方法CalculateFolderSize
            IAsyncResult ret=d.BeginInvoke(FolderName,null,null);

            Console.WriteLine("正在计算中,请耐心等待……");
            //阻塞,等到调用完成,取出结果
            long size = d.EndInvoke(ret);
            
            Console.WriteLine("\n计算完成。文件夹{0}的容量为:{1}字节\n", FolderName, size);
        }
    }
}

以上就是同步与异步原理上的简单差别:是否在同一个线程中执行不同的方法,当然通过这两个例子还看不到同步与异步的本质区别,这需要对异步机制进行更加深入的学习!

  • 0
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 2
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值