Async(异步)(一)

在谈到异步的概念时,先要了解几个概念了。

什么是进程?

当一个程序开始运行时,它就是一个进程,进程包括运行中的程序和程序所使用到的内存和系统资源。

而一个进程又是由多个线程所组成的

什么是线程?

线程是程序中的一个执行流,每个线程都有自己的专有寄存器(栈指针、程序计数器等),但代码区是共享的,即不同的线程可以执行同样的函数。

什么是多线程?

多线程是指程序中包含多个执行流,即在一个程序中可以同时运行多个不同的线程来执行不同的任务,也就是说允许单个程序创建多个并行执行的线程来完成各自的任务。

了解完进程、线程、多线程后,再来了解同步和异步

同步方法调用在程序继续执行之前需要等待同步方法执行完毕返回结果,简单来说就是按照方法的执行顺序从上向下一次执行。

异步方法则在被调用之后立即返回以便程序在被调用方法完成其任务的同时执行其它操作。

举个例子:比如张三叫你吃饭,你说有点事需要完成后再去吃饭,而张三等你做完了事之后,再和你一起去吃饭。这就是同步

或者张三叫你吃饭,你说有点事需要完成后再去吃饭,但是张三就只是叫了下你吃饭,他也没有等你回答,就自己独自去吃了。这就可以是异步。

那么在程序中如何声明一个同步,异步呢,其实提到同步异步,就必须熟悉委托,不熟悉的可以看前面的博客,在这里就不多阐述了。

首先声明一个委托和一个普通方法

         private delegate void DoSomethingDelegate(string name);

         Console.WriteLine("****************btnAsync_Click Start {0}***************", Thread.CurrentThread.ManagedThreadId);

         DoSomethingDelegate method = new DoSomethingDelegate(this.DoSomethingLong);

      method.Invoke("123");

Console.WriteLine("****************btnAsync_Click   End {0}***************", Thread.CurrentThread.ManagedThreadId);

        private void DoSomethingLong(string name)
        {
            Console.WriteLine("****************DoSomethingLong Start {0}***************", Thread.CurrentThread.ManagedThreadId);
            long lResult = 0;
            for (int i = 0; i < 10000000; i++)
            {
                lResult += i;
            }
            Thread.Sleep(2000);

            Console.WriteLine("****************DoSomethingLong   End {0}***************", Thread.CurrentThread.ManagedThreadId);

 

可以看出程序的运行程序是从上向下执行的,这就是同步。

但是如果是异步调用的情况,就是另外一种情况

method.BeginInvoke("123", null, null);

你会发现异步时,程序不管你调用的方法有没有执行,它直接往下执行,而异步调用的方法开启了新线程,在后面继续执行。

那么上面BeginInvoke中两个null参数代表着什么呢。

简单来说就是一个是IAsyncResult 类型的委托,和一个动态参数(而一般来说最后一个参数一般当做状态参数来使用)。

举个例子

            IAsyncResult asyncResult = null;

            AsyncCallback callback = t =>
                {
                    Console.WriteLine(t.Equals(asyncResult));

                    Console.WriteLine(t.AsyncState);
                    Console.WriteLine("这里是回调函数 {0}", Thread.CurrentThread.ManagedThreadId);
                };

            asyncResult = method.BeginInvoke("123", callback, "ming");

 

通过例子也可以得出 t.AsyncState其实和你BeginInvoke的第三个参数是相等的。其实这个例子还可以得出,method.BeginInvoke()得到的返回值是和BeginInvoke()第二个参数是相等的。

但是,假如有个这样的需求,等待异步结束后,主线程还要做事儿,通过前面的例子可以得出,单单使用BeginInvoke()是做不到的,在这里介绍几种方式:

1)IsCompleted属性,他会判断异步是否完成,在这里就可以加一个判断。

            int i = 1;
            while (!asyncResult.IsCompleted)
            {
                Console.WriteLine("*****正在计算,已完成{0}%。。。。", 10 * i++);
                Thread.Sleep(100);
            }

  

这样他会等异步结束后跳出循环,再继续执行主线程。但是这样的做法会影响一点效率,因为它不是在异步结束的第一时间就跳出循环,会有一个sleep时间。

2)WaitOne()方法

  asyncResult.AsyncWaitHandle.WaitOne();//一直等待
  asyncResult.AsyncWaitHandle.WaitOne(-1);//一直等待
  asyncResult.AsyncWaitHandle.WaitOne(1000);//等待1000毫秒,超时就不等待了

3)EndInvoke()方法

  method.EndInvoke(asyncResult);

其实EndInvoke()除了会等待线程之外,他还可以接受一个返回值输出

假设有一个带string类型返回值的委托,如果直接invoke也可以得到这个返回值

   Func<int, string> func1 = i =>
                {
                    DoSomethingLong("btnAsync_Click");
                    return "二零一七给力";
                };  string s = func1.Invoke(123);

但是你需要开启一个新的线程,而用BeginInvoke是不能得到返回值的,因为它只能返回的是IAsyncResult类型。

这个时候就需要EndInvoke,来实现这个需求

string sResult = func1.EndInvoke(asyncResult)

总的来说这三种方式各有各的优势,需要根据实际情况来使用。

未完待续。。。

时间: 2024-08-09 05:11:17

Async(异步)(一)的相关文章

使用spring的@Async异步执行方法

应用场景: 1.某些耗时较长的而用户不需要等待该方法的处理结果 2.某些耗时较长的方法,后面的程序不需要用到这个方法的处理结果时 在spring的配置文件中加入对异步执行的支持 <beans xmlns="http://www.springframework.org/schema/beans" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:tx="http://www.spri

Async异步编程入门示例

1 using System; 2 using System.Collections.Generic; 3 using System.Linq; 4 using System.Text; 5 using System.Threading.Tasks; 6 7 namespace AsyncDemo 8 { 9 class Program 10 { 11 static void Main(string[] args) 12 { 13 Console.WriteLine("异步方法测试开始!&quo

js:nodejs通过async异步提交事务数据

一,async异步编程 1,异步编程是指由于异步I/O等因素,无法同步获得执行结果时, 在回调函数中进行下一步操作的代码编写风格,常见的如setTimeout函数.ajax请求等等 waterfall函数 瀑布流 waterfall每个函数产生的值,都将传给下一个函数 2,事务 数据库事物(transaction)就是一组SQL语句,这组SQL语句是一个逻辑工作单元.我们可以认为事务就是一组不可 分割的SQL语句,在执行时,应该作为一个整体永久性地修改数据库的内容,或者作为一个整体取消对数据库的

第二章 有什么理由使用Async异步编程

p { display: block; margin: 3px 0 0 0; } --> 写在前面 在学异步,有位园友推荐了<async in C#5.0>,没找到中文版,恰巧也想提高下英文,用我拙劣的英文翻译一些重要的部分,纯属娱乐,简单分享,保持学习,谨记谦虚. 如果你觉得这件事儿没意义翻译的又差,尽情的踩吧.如果你觉得值得鼓励,感谢留下你的赞,在今后每一次应该猛烈突破的时候,不选择知难而退.在每一次应该独立思考的时候,不选择随波逐流,应该全力以赴的时候,不选择尽力而为,愿爱技术的园

利用Spring MVC中@Async异步特性改善耗时操作的用户体验

Web应用中,有时会遇到一些耗时很长的操作(比如:在后台生成100张报表再呈现,或 从ftp下载若干文件,综合处理后再返回给页面下载),用户在网页上点完按钮后,通常会遇到二个问题:页面超时.看不到处理进度. 对于超时,采用异步操作,可以很好的解决这个问题,后台服务收到请求后,执行异步方法不会阻塞线程,因此就不存在超时问题.但是异步处理的进度用户也需要知道,否则不知道后台服务何时完成,不知道是否继续等候,还是关掉页面. 思路: 1.browser -> Spring-MVC Controller

springboot+async异步接口实现和调用

什么是异步调用? 异步调用是相对于同步调用而言的,同步调用是指程序按预定顺序一步步执行,每一步必须等到上一步执行完后才能执行,异步调用则无需等待上一步程序执行完即可执行. 如何实现异步调用? 多线程,这是很多人第一眼想到的关键词,没错,多线程就是一种实现异步调用的方式. 在非spring目项目中我们要实现异步调用的就是使用多线程方式,可以自己实现Runable接口或者集成Thread类,或者使用jdk1.5以上提供了的Executors线程池. StrngBoot中则提供了很方便的方式执行异步调

async异步注解和aspect切面注解等注解的原理

在我们使用spring框架的过程中,在很多时候我们会使用@async注解来异步执行某一些方法,提高系统的执行效率.今天我们来探讨下spring是如何完成这个功能的. 1.spring 在扫描bean的时候会扫描方法上是否包含@async的注解,如果包含的,spring会为这个bean动态的生成一个子类,我们称之为代理类(?). 2.代理类是继承我们所写的bean的,然后把代理类注入进来,在执行此方法时会到代理类中,代理类判断此方法需要异步执行,就不会调用父类 (我们原本写的bean)的对应方法.

Async 异步转同步详细流程解释

安装 npm install async --save 地址 https://github.com/caolan/async Async的内容主要分为三部分 流程控制: 简化九种常见的流程的处理 集合处理:如何使用异步操作处理集中的数据 工具类:几个常用的工具类 本文主要介绍流程控制部分,后续内容持续更新,由于node.js是异步编程模型,有许多在同步编程中很容易做到的事情,现在就会变的很麻烦,并且存在很多的callback.但是,Async的流程控制给我们coder带来了许多便利. 1.ser

SpringBoot @Async 异步处理业务逻辑和发短信逻辑

有个业务场景,业务数据审核通过后需要给用户发短信,发短信过程比较耗时,可能需要几秒甚至十几秒,因此使用异步发短信 使用了注解@Async来实现: 1.SpringApplication启用注解@EnableAsync @SpringBootApplication @ImportResource(locations = { "classpath:/spring/spring-*.xml" }) @EnableTransactionManagement(proxyTargetClass=t

Spring Boot Async异步执行

异步调用就是不用等待结果的返回就执行后面的逻辑,同步调用则需要等带结果再执行后面的逻辑. 通常我们使用异步操作都会去创建一个线程执行一段逻辑,然后把这个线程丢到线程池中去执行,代码如下: ExecutorService executorService = Executors.newFixedThreadPool(10); executorService.execute(() -> { try { // 业务逻辑 } catch (Exception e) { e.printStackTrace(