• C#(99):异步和多线程的区别


    区别和联系

          异步和多线程有什么区别?其实,异步是目的,而多线程是实现这个目的的方法。异步是说,A发起一个操作后(一般都是比较耗时的操作,如果不耗时的操作就没有必要异步了),可以继续自顾自的处理它自己的事儿,不用干等着这个耗时操作返回。.Net中的这种异步编程模型,就简化了多线程编程,我们甚至都不用去关心Thread类,就可以做一个异步操作出来。

          异步有的时候用普通的线程,有的时候用系统的异步调用功能。有一些IO操作也是异步的,但是未必需要一个线程来运行。例如:硬件是有DMA功能的,在调用DMA传输数据的时候,CPU是不需要执行处理的,只需要发起传输和等待传输结束即可。具体到.net平台,比如Socket的BeginSend,如果是运行在Windows    2000以后的平台,在底层就会调用异步的完成端口来发送。

          .Net中的异步执行其实使用的是异步委托。异步委托将要执行的方法提交到.net的线程池,由线程池中的线程来执行异步方法。

    适用范围

    • 当需要执行I/O操作时,使用异步操作更合适。I/O操作不仅包括了直接的文件、网络的读写,还包括数据库操作、Web Service、HttpRequest以及.net Remoting等跨进程的调用。
    • 而线程的适用范围则是那种需要长时间CPU运算的场合,例如耗时较长的图形处理和算法执行。

    异步的一个示例

      大家可能都知道,使用delegate可以“自动”使一个方法可以进行异步的调用。从直觉上来说,我觉得是由编译器或者CLR使用了另外的线程来执行目标方法。到底是不是这样呢??让我们来用一段代码证明一下吧。

    delegate void AsyncFoo(int i);
    
    static void Main(string[] args)
    {
        PrintCurrThreadInfo("Main()");
        for (int i = 0; i < 10; i++)
        {
            PostAsync();
        }
        Console.ReadLine();
    }
    ///<summary>
    /// 输出当前线程的信息
    ///</summary>
    ///<param name="name">方法名称</param>
    
    static void PrintCurrThreadInfo(string name)
    {
        Console.WriteLine("Thread Id of " + name + " is: " + Thread.CurrentThread.ManagedThreadId + ", current thread is "
                 + (Thread.CurrentThread.IsThreadPoolThread ? "" : "not ")
                 + "thread pool thread.");
    }
    
    
    ///<summary>
    /// 投递一个异步调用
    ///</summary>
    static void PostAsync()
    {
        AsyncFoo caller = new AsyncFoo(Foo);
        caller.BeginInvoke(1000, new AsyncCallback(FooCallBack), caller);
    }
    
    ///<summary>
    /// 测试方法,Sleep一定时间
    ///</summary>
    ///<param name="i">Sleep的时间</param>
    static void Foo(int i)
    {
        PrintCurrThreadInfo("Foo()");
        Thread.Sleep(i);
    }
    
    static void FooCallBack(IAsyncResult ar)
    {
        PrintCurrThreadInfo("FooCallBack()");
        AsyncFoo caller = (AsyncFoo)ar.AsyncState;
        caller.EndInvoke(ar);
    }

    这段代码代码的输出如下:

    Thread Id of Main() is: 1, current thread is not thread pool thread.
    Thread Id of Foo() is: 3, current thread is thread pool thread.
    Thread Id of FooCallBack() is: 3, current thread is thread pool thread.
    Thread Id of Foo() is: 3, current thread is thread pool thread.
    Thread Id of Foo() is: 4, current thread is thread pool thread.
    Thread Id of Foo() is: 5, current thread is thread pool thread.
    Thread Id of FooCallBack() is: 3, current thread is thread pool thread.
    Thread Id of Foo() is: 3, current thread is thread pool thread.
    Thread Id of FooCallBack() is: 4, current thread is thread pool thread.
    Thread Id of Foo() is: 4, current thread is thread pool thread.
    Thread Id of Foo() is: 6, current thread is thread pool thread.
    Thread Id of FooCallBack() is: 5, current thread is thread pool thread.
    Thread Id of Foo() is: 5, current thread is thread pool thread.
    Thread Id of Foo() is: 7, current thread is thread pool thread.
    Thread Id of FooCallBack() is: 3, current thread is thread pool thread.
    Thread Id of Foo() is: 3, current thread is thread pool thread.
    Thread Id of FooCallBack() is: 4, current thread is thread pool thread.
    Thread Id of FooCallBack() is: 6, current thread is thread pool thread.
    Thread Id of FooCallBack() is: 5, current thread is thread pool thread.
    Thread Id of FooCallBack() is: 7, current thread is thread pool thread.
    Thread Id of FooCallBack() is: 3, current thread is thread pool thread.
    

    从输出可以看出,.net 使用 delegate 来“自动”生成的异步调用是使用了另外的线程(而且是线程池线程)。

  • 相关阅读:
    C++ 将对象写入文件 并读取
    IronPython fail to add reference to WebDriver.dll
    How to Capture and Decrypt Lync Server 2010 TLS Traffic Using Microsoft Tools
    .net code injection
    数学系学生应该知道的十个学术网站
    Difference Between Currency Swap and FX Swap
    Swift开源parser
    谈谈我对证券公司一些部门的理解(前、中、后台)[z]
    JDK8记FullGC时候Metaspace内存不会被垃圾回收
    JVM源码分析之JDK8下的僵尸(无法回收)类加载器[z]
  • 原文地址:https://www.cnblogs.com/springsnow/p/9428818.html
Copyright © 2020-2023  润新知