• C#3.0学习笔记(12)进程,线程和异步编程


      离职在家,没有什么事做,所以借这个机会总结一下关于异步编程的技术来跟各位园友分享。

    1,什么叫进程?什么叫线程?

      进程:进程就是一组资源,它们构成了一个正在运行的程序。这些资源包括虚拟地址空间,文件句柄以及程序启动需要的其他东西的载体。当我们启动一个程序时,系统在内存中  

      就创建了一个新的进程(Process)。

      线程:在进程中,系统创建了一个叫做线程(thread)的内核对象,线程体现了一个程序的真实执行情况。一旦程序准备完毕,系统在线程中开始执行Main方法的第一条语句。默

      认情况下,一个进程只包含一个线程,它从程序开始执行一直到程序结束。

    2,什么叫异步编程(或称为多线程)?

      在理解什么叫异步编程之前,我们先来看看什么叫同步编程,到目前为止,我们前面讲的所有程序都只有一个线程,并且从程序的第一行语句到最后一行语句顺序执行,这就叫同             

      步编程。异步编程指的是程序发起多个线程,它们在理论上是在同一时间执行的。(其实不一定真的在同一时间执行)  

    下面来介绍两种简单但非常强大的多线程技术,异步委托和计时器:

    异步委托:

    使用异步委托有三种标准模式:

    1,等待一直到完成(wait-until-done)模式:在发起了异步方法以及做了一些其它处理后,原始线程就中断并且等异步方法完成之后再继续。

    2,轮询(Polling)模式:原始线程定期检查发起的线程是否完成,如果没有则可以继续做一些其它的事情。

    3,回调(Callback)模式:原始线程一直执行,无需等待或检查发起的线程是否完成。在发起的线程中的引用方法完成之后,发起的线程就会调用回调方法,由回调方法在调用EndInvoke之前处理异步方法的

      结构。

    下面是这三种模式的执行过程图示:

     下面就看看这三种模式分别的完整示例:

    1,等待一直到结束模式的示例:

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

    namespace thread1
    {
    delegate long MyDel(int first,int second); //声明委托类型
    class Program
    {
    static long Sum(int x, int y) //声明异步方法,方法匹配委托。
    {
    Console.WriteLine(" Inside Sum");
    Thread.Sleep(100); //调用Thread类的Sleep方法将它自己挂起0.1秒。
    return x + y;
    }

    static void Main(string[] args)
    {
    MyDel del = new MyDel(Sum); //创建委托对象,并使用Sum方法来初始化它的调用列表

    Console.WriteLine("Before BeginInvoke");
    IAsyncResult iar = del.BeginInvoke(3, 5, null, null); //开始异步调用,BeginInvoke返回一个IAsyncResult接口的引用。
    Console.WriteLine("After BeginInvoke");

    Console.WriteLine("Doing stuff");

    long result = del.EndInvoke(iar); //等待结束并获取结果。必须把IAsyncResult对象的引用作为参数。
    Console.WriteLine("Ater EndInvoke:{0}",result);
    Console.ReadKey();
    }
    }
    }

    程序输出结果为:

    2,轮询(Polling)模式的示例:

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

    namespace thread2
    {
    delegate long MyDel(int first,int second); //声明委托类型。
    class Program
    {
    static void Main(string[] args)
    {
    MyDel del = new MyDel(Sum); //创建委托对象。

    IAsyncResult iar = del.BeginInvoke(3, 5, null, null); //发起异步调用,BeginInvoke返回一个IAsyncResult接口的引用。
    Console.WriteLine("After BeginInvoke");

    while (!iar.IsCompleted) //调用IAsyncResult接口的IsCompleted属性检查异步方法是否完成。
    {
    Console.WriteLine("Not Done");

    //继续处理。这里的“处理”仅仅是由0数到10000000。
    for (long i = 0; i < 10000000; i++)
    ; //空语句。
    }
    Console.WriteLine("Done");

    long result = del.EndInvoke(iar); //调用委托的EndInvoke方法来获取接口并进行清理。
    Console.WriteLine("Result:{0}",result);
    Console.ReadKey();

    }

    static long Sum(int x, int y) //声明方法匹配委托。
    {
    Console.WriteLine(" Inside Sum");
    Thread.Sleep(500); //调用Thread类的Sleep方法将它自己挂起0.5秒。
    return x + y;
    }
    }
    }

    程序输出结果为:

    3,回调(Callback)模式的示例代码:

    using System;
    using System.Collections.Generic;
    using System.Linq;
    using System.Text;
    using System.Threading;
    using System.Runtime.Remoting.Messaging;

    namespace thread3
    {
    delegate long MyDel(int first,int second); //声明委托类型。

    class Program
    {
    static long Sum(int x, int y) //声明方法匹配委托。
    {
    Console.WriteLine(" Inside Sum");
    Thread.Sleep(100); //调用Thread类的Sleep方法将它自己挂起0.1秒。
    return x + y;
    }

    static void CallWhenDone(IAsyncResult iar) //声明回调方法。
    {
    Console.WriteLine(" Inside CallWhenDone");
    AsyncResult ar = (AsyncResult)iar; //通过引用转换,将接口引用转换为AsyncResult类对象的引用。
    MyDel del = (MyDel)ar.AsyncDelegate; //调用类对象的AsyncDelegate属性并把它转化为委托类型,这样我们就可以调用委托的EndInvoke方法了。
    long result = del.EndInvoke(iar); //结束调用,获取异步方法调用的返回值,释放线程所用资源。
    Console.WriteLine(" The result is {0}",result);
    }

    static void Main(string[] args)
    {
    MyDel del = new MyDel(Sum); //创建委托对象。

    Console.WriteLine("Before BeginInvoke");
    IAsyncResult iar = del.BeginInvoke(3,5,CallWhenDone,null);

    Console.WriteLine("Doing more work in Main");
    Thread.Sleep(500);
    Console.WriteLine("Done with Main,Exiting");
    Console.ReadKey();
    }
    }
    }

    程序输出结果为:

    计时器:

    计时器提供了另外一种正规的重复运行异步方法的方法。尽管在.NET BCL中有好几个可用的Timer类,但在这里我只会介绍System.Threading命名空间中的一个。

    使用计时器需要注意的重要事项如下:

    1,计时器在每次时间到期后调用回调方法。回调方法必须是TimerCallback委托形式的。

    2,当计时器到期之后,系统会从线程池中的线程上开启一下回调方法,提供state对象作为其参数,并且开始运行。

    3,Timer类的构造函数接受回调方法名称,dueTime,period以及state作为参数,其最为常用的构造函数形式如下:

      Timer myTimer=new Timer(MyCallback,someObject,2000,1000);

      注:MyCallback为回调方法的名称。

        someObject为传给回调的对象。

        2000即dueTime表示2000毫秒后第一次调用。

        1000即period表示每1000毫秒调用一次。

    示例如下:

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

    namespace thread4
    {
    class Program
    {
    int TimesCalled = 0;

    protected void Display(object state)//声明回调方法。
    {
    Console.WriteLine("{0}{1}",(string)state,++TimesCalled);
    }

    static void Main(string[] args)
    {
    Program p = new Program();//创建类的实例。

    Timer myTimer = new Timer(p.Display,"Processing timer event",2000,1000);//创建Timer类对象。
    Console.WriteLine("Timer start");
    Console.ReadKey();
    }
    }
    }

    这段代码在被关闭前的5秒内产生了如下的输出:

      以上就是这次总结的关于多线程编程方面的知识,写了一下午了。正好今天是我的27岁的生日,我得去准备请同事吃饭了,在这里也希望自己在新的一年里身体健康,工作顺利。


  • 相关阅读:
    171 01 Android 零基础入门 03 Java常用工具类02 Java包装类 01 包装类简介 01 Java包装类内容简介
    170 01 Android 零基础入门 03 Java常用工具类01 Java异常 08 Java异常总结 01 异常总结
    169 01 Android 零基础入门 03 Java常用工具类01 Java异常 07 异常链 01 异常链简介
    168 01 Android 零基础入门 03 Java常用工具类01 Java异常 06 自定义异常 01 自定义异常类
    167 01 Android 零基础入门 03 Java常用工具类01 Java异常 05 使用throw和throws实现异常处理 02 使用throw抛出异常对象
    166 01 Android 零基础入门 03 Java常用工具类01 Java异常 05 使用throw和throws实现异常处理 01 使用throws声明异常类型
    165 01 Android 零基础入门 03 Java常用工具类01 Java异常 04 使用try…catch…finally实现异常处理 05 return关键字在异常处理中的使用
    DevExpress WPF v20.2版本亮点放送:全新升级的PDF Viewer
    界面控件DevExpress使用教程:Dashboard – 自定义导出
    DevExpress WinForms帮助文档:表单控件
  • 原文地址:https://www.cnblogs.com/mcgrady/p/2252793.html
Copyright © 2020-2023  润新知