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

什么是进程?

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

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

什么是线程?

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

什么是多线程?

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

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

同步方法调用在程序继续执行之前需要等待同步方法执行完毕返回结果,简单来说就是按照方法的执行顺序从上向下一次执行。
异步方法则在被调用之后立即返回以便程序在被调用方法完成其任务的同时执行其它操作。

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

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

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

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

         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)

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

未完待续。。。

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

  1. 异步编程系列第01章 Async异步编程简介

    p { display: block; margin: 3px 0 0 0; } --> 2016.10.11补充 三个月过去了,回头来看,我不得不承认这是一系列失败的翻译.过段时间,我将重新翻 ...

  2. @Async异步注解与SpringBoot结合使用

    当你在service层需要启动异步线程去执行某些分支任务,又不希望显式使用Thread等线程相关类,只想专注于实现业务逻辑代码开发,可以使用@Async异步注解. 1. 使用@Async 异步注解 C ...

  3. C#.NET使用Task,await,async,异步执行控件耗时事件(event),不阻塞UI线程和不跨线程执行UI更新,以及其他方式比较

    使用Task,await,async,异步执行事件(event),不阻塞UI线程和不跨线程执行UI更新 使用Task,await,async 的异步模式 去执行事件(event) 解决不阻塞UI线程和 ...

  4. spring boot(17)-@Async异步

    验证码的异步机制 上一篇讲过可以用邮件发验证码,通常我们在某网站发验证码时,首先会提示验证码已发送,请检查邮箱或者短信,这就是图中的1和3.然而此时查看邮箱或短信可能并没有收到验证码,往往要过几秒种才 ...

  5. 在 .NET 4.0 下编写扩展代码以支持 async 异步编程

    微软在C# 5中引入了async.await这两个异步编程的关键字,要使用这两个关键字需要你的IDE支持C#5.0语法,也就意味着你需要使用VS 2012版本以上IDE,或者在Vs2010卸载其编译器 ...

  6. Spring Boot (18) @Async异步

    通常我们在某网站发送邮件验证码时,首先会提示验证码已发送,然而此时可能没有收到验证码,过几秒种才真正的收到.如果是同步会先验证发送是否成功然后再通知,如果是异步可以先通知用户已发送,并释放请求,然后再 ...

  7. @Async 异步注释 @EnableAsync

    @SpringBootApplication @ComponentScan(basePackages = "com.fddsfsg") //@EnableSwagger2 @Ena ...

  8. 第六节:前后端交互之axios用法及async异步编程

    一. axios用法 参考: API文档: https://www.kancloud.cn/yunye/axios/234845 GitHub: https://github.com/axios/ax ...

  9. Spring Boot -- Spring Boot之@Async异步调用、Mybatis、事务管理等

    这一节将在上一节的基础上,继续深入学习Spring Boot相关知识,其中主要包括@Async异步调用,@Value自定义参数.Mybatis.事务管理等. 本节所使用的代码是在上一节项目代码中,继续 ...

  10. spring boot:使用async异步线程池发送注册邮件(spring boot 2.3.1)

    一,为什么要使用async异步线程池? 1,在生产环境中,有一些需要延时处理的业务场景: 例如:发送电子邮件, 给手机发短信验证码 大数据量的查询统计 远程抓取数据等 这些场景占用时间较长,而用户又没 ...

随机推荐

  1. Xmpp学习之Android-smack入门指导

    Xmpp学习之Android-smack入门指导 版权声明:本文为博主原创文章,未经博主允许不得转载. 转载请表明出处:http://www.cnblogs.com/cavalier-/p/69404 ...

  2. Postgres Linux 维护 随笔1(启动篇)

    关于postgres 起停操作随笔 Linux 环境下,对Postgres 起停常用代码 Postgres 启动 : pg_ctl start Postgres 停止 : pg_ctl stop Po ...

  3. (原创)Python 自动化测试框架详解

    自己折腾了一个python的自动化测试框架,梳理了一下流程,简单分享一下. 项目背景 B/S架构,进行用户界面的自动化测试 工具选择 python开发的自动化测试框架,足够灵活,可以随时根据需求进行变 ...

  4. intel hex 格式的几个链接

    intel hex GENERAL: INTEL HEX FILE FORMAT Intel Hex文件格式说明 - starspace - 博客园 C# Hex文件转bin文件 - bule - 博 ...

  5. Nmap绕过防火墙&脚本的使用

    Nmap是用于端口扫描,服务检测,甚至是漏洞扫描等多种功能的强大工具.Nmap从入门到高级覆盖了许多基础的概念和命令,在这篇文章的第二部分,我将提及Nmap一些高级的技术. 防火墙和入侵检测系统(ID ...

  6. css简单了解

    今天主要是说一下css样式表!HTML结合他使用可以是HTML页面变得很绚丽多彩! 先简单介绍一下为什么要使用CSS(Cascading Style Sheets)层叠样式表! 1.因为CSS样式表可 ...

  7. Chapter 1:Introduction

    作者:桂. 时间:2017-05-24  08:06:45 主要是<Speech enhancement: theory and practice>的读书笔记,全部内容可以点击这里. 1. ...

  8. Access denied for user 'root'@'localhost' (using password: NO)错误的解决方案

    在windows下使用PHP连接MYSQL数据库,确定MYSQL的服务已经启动了,而且Workbench也是可以连上去的,但是始终网页测试都提示Access Denied. 最终解决办法: set p ...

  9. MongoDB一个基于分布式文件存储的数据库(介于关系数据库和非关系数据库之间的数据库)

    1:MongoDB的官方网址:https://www.mongodb.com   MongoDB的中文社区:http://www.mongoing.com/(老外也很看重中国市场啊,知道大家英语不好, ...

  10. win7安装oracle10g数据库 提示“…实际版本为6.1”

    1.最重要的是需要以管理员的身份操作 2.修改重要的文件 然后解压,在目录中找到refhost.xml(有两个,我的一个是在stage\prereq\db目录下,一个是在stage\prereq\db ...