本站业务范围:1、PC端软件开发、网站开发 2、移动端APP、网站、微信接口、微商城开发 3、视频教程、课程设计和辅导 4、单片机开发 5、串口通讯调试
 当前位置:文章中心 >> NodeJs视频教程
立即购买视频教程 C#同步方法和异步方法的区别(比较经典)
夜鹰教程网 来源:www.yyjcw.com 日期:2017-11-5 14:27:02
c#异步编程。

这篇文章不能解决你的问题?我们还有相关视频教程云课堂 全套前端开发工程师培训课程

微信号:yyjcw10000 QQ:1416759661  远程协助需要加QQ!

业务范围:视频教程|程序开发|在线解答|Demo制作|远程调试| 点击查看相关的视频教程

技术范围:全端开发/前端开发/webapp/web服务/接口开发/单片机/C#/java/node/sql server/mysql/mongodb/android/。 



同步方法和异步方法的区别

同步方法调用在程序继续执行之前需要等待同步方法执行完毕返回结果
异步方法则在被调用之后立即返回以便程序在被调用方法完成其任务的同时执行其它操作
异步编程概览

.NET Framework 允许您异步调用任何方法。定义与您需要调用的方法具有相同签名的委托;公共语言运行库将自动为该委托定义具有适当签名

的 BeginInvoke 和 EndInvoke 方法。

BeginInvoke 方法用于启动异步调用。它与您需要异步执行的方法具有相同的参数,只不过还有两个额外的参数(将在稍后描述)。

BeginInvoke 立即返回,不等待异步调用完成。
BeginInvoke 返回 IasyncResult,可用于监视调用进度。

EndInvoke 方法用于检索异步调用结果。调用 BeginInvoke 后可随时调用 EndInvoke 方法;如果异步调用未完成,EndInvoke 将一直阻塞到

异步调用完成。EndInvoke 的参数包括您需要异步执行的方法的 out 和 ref 参数(在 Visual Basic 中为 <Out> ByRef 和 ByRef)以及由

BeginInvoke 返回的 IAsyncResult。

四种使用 BeginInvoke 和 EndInvoke 进行异步调用的常用方法。调用了 BeginInvoke 后,可以:

1.进行某些操作,然后调用 EndInvoke 一直阻塞到调用完成。
2.使用 IAsyncResult.AsyncWaitHandle 获取 WaitHandle,使用它的 WaitOne 方法将执行一直阻塞到发出 WaitHandle 信号,然后调用

EndInvoke。这里主要是主程序等待异步方法,等待异步方法的结果。
3.轮询由 BeginInvoke 返回的 IAsyncResult,IAsyncResult.IsCompeted确定异步调用何时完成,然后调用 EndInvoke。此处理个人认为与
相同。
4.将用于回调方法的委托传递给 BeginInvoke。该方法在异步调用完成后在 ThreadPool 线程上执行,它可以调用 EndInvoke。这是在强制装

换回调函数里面IAsyncResult.AsyncState(BeginInvoke方法的最后一个参数)成委托,然后用委托执行EndInvoke。
警告   始终在异步调用完成后调用 EndInvoke。

以上有不理解的稍后可以再理解。

 
例子

1)先来个简单的没有回调函数的异步方法例子

请再运行程序的时候,仔细看注释,对理解很有帮助。还有,若将注释的中的两个方法都同步,你会发现异步运行的速度优越性。

 
using System;

 namespace ConsoleApplication1
 {
     class Class1
     {
         //声明委托
         public delegate void AsyncEventHandler();
 
         //异步方法
         void Event1()
        {
            Console.WriteLine("Event1 Start");
            System.Threading.Thread.Sleep(4000);
            Console.WriteLine("Event1 End");
        }

        // 同步方法
        void Event2()
        {
            Console.WriteLine("Event2 Start");
            int i=1;
            while(i<1000)
            {
                i=i+1;
                Console.WriteLine("Event2 "+i.ToString());
            }
            Console.WriteLine("Event2 End");
        }

        [STAThread]
        static void Main(string[] args)
        {
            long start=0;
            long end=0;
            Class1 c = new Class1();
            Console.WriteLine("ready");
            start=DateTime.Now.Ticks;

            //实例委托
            AsyncEventHandler asy = new AsyncEventHandler(c.Event1);
            //异步调用开始,没有回调函数和AsyncState,都为null
            IAsyncResult ia = asy.BeginInvoke(null, null);
            //同步开始,
            c.Event2();
            //异步结束,若没有结束,一直阻塞到调用完成,在此返回该函数的return,若有返回值。

           
            asy.EndInvoke(ia);

            //都同步的情况。
            //c.Event1();
            //c.Event2();
           
            end =DateTime.Now.Ticks;
            Console.WriteLine("时间刻度差="+ Convert.ToString(end-start) );
            Console.ReadLine();
        }
    }
}


 

2)下面看有回调函数的WebRequest和WebResponse的异步操作。

using System;
using System.Net;
using System.Threading;
using System.Text;
using System.IO;


// RequestState 类用于通过
// 异步调用传递数据
public class RequestState
{
    const int BUFFER_SIZE = 1024;
    public StringBuilder RequestData;
    public byte[] BufferRead;
    public HttpWebRequest Request;
    public Stream ResponseStream;
    // 创建适当编码类型的解码器
    public Decoder StreamDecode = Encoding.UTF8.GetDecoder();

    public RequestState()
    {
        BufferRead = new byte[BUFFER_SIZE];
        RequestData = new StringBuilder("");
        Request = null;
        ResponseStream = null;
    }
}

// ClientGetAsync 发出异步请求
class ClientGetAsync
{
    public static ManualResetEvent allDone = new ManualResetEvent(false);
    const int BUFFER_SIZE = 1024;

    public static void Main(string[] args)
    {

        if (args.Length < 1)
        {
            showusage();
            return;
        }

        // 从命令行获取 URI
        Uri HttpSite = new Uri(args[0]);

        // 创建请求对象
        HttpWebRequest wreq = (HttpWebRequest)WebRequest.Create(HttpSite);

        // 创建状态对象
        RequestState rs = new RequestState();

        // 将请求添加到状态,以便它可以被来回传递
        rs.Request = wreq;

        // 发出异步请求
        IAsyncResult r = (IAsyncResult)wreq.BeginGetResponse(new AsyncCallback(RespCallback), rs);

        // 将 ManualResetEvent 设置为 Wait,
        // 以便在调用回调前,应用程序不退出
        allDone.WaitOne();
    }

    public static void showusage()
    {
        Console.WriteLine("尝试获取 (GET) 一个 URL");
        Console.WriteLine("\r\n用法::");
        Console.WriteLine("ClientGetAsync URL");
        Console.WriteLine("示例::");
        Console.WriteLine("ClientGetAsync http://www.microsoft.com/net/");
    }

    private static void RespCallback(IAsyncResult ar)
    {
        // 从异步结果获取 RequestState 对象
        RequestState rs = (RequestState)ar.AsyncState;

        // 从 RequestState 获取 HttpWebRequest
        HttpWebRequest req = rs.Request;

        // 调用 EndGetResponse 生成 HttpWebResponse 对象
        // 该对象来自上面发出的请求
        HttpWebResponse resp = (HttpWebResponse)req.EndGetResponse(ar);

        // 既然我们拥有了响应,就该从
        // 响应流开始读取数据了
        Stream ResponseStream = resp.GetResponseStream();

        // 该读取操作也使用异步完成,所以我们
        // 将要以 RequestState 存储流
        rs.ResponseStream = ResponseStream;

        // 请注意,rs.BufferRead 被传入到 BeginRead。
        // 这是数据将被读入的位置。
        IAsyncResult iarRead = ResponseStream.BeginRead(rs.BufferRead, 0, BUFFER_SIZE, new AsyncCallback(ReadCallBack), rs);
    }


    private static void ReadCallBack(IAsyncResult asyncResult)
    {
        // 从 asyncresult 获取 RequestState 对象
        RequestState rs = (RequestState)asyncResult.AsyncState;

        // 取出在 RespCallback 中设置的 ResponseStream
        Stream responseStream = rs.ResponseStream;

        // 此时 rs.BufferRead 中应该有一些数据。
        // 读取操作将告诉我们那里是否有数据
        int read = responseStream.EndRead(asyncResult);

        if (read > 0)
        {
            // 准备 Char 数组缓冲区,用于向 Unicode 转换
            Char[] charBuffer = new Char[BUFFER_SIZE];

            // 将字节流转换为 Char 数组,然后转换为字符串
            // len 显示多少字符被转换为 Unicode
            int len = rs.StreamDecode.GetChars(rs.BufferRead, 0, read, charBuffer, 0);
            String str = new String(charBuffer, 0, len);

            // 将最近读取的数据追加到 RequestData stringbuilder 对象中,
            // 该对象包含在 RequestState 中
            rs.RequestData.Append(str);


            // 现在发出另一个异步调用,读取更多的数据
            // 请注意,将不断调用此过程,直到
            // responseStream.EndRead 返回 -1
            IAsyncResult ar = responseStream.BeginRead(rs.BufferRead, 0, BUFFER_SIZE, new AsyncCallback(ReadCallBack), rs);
        }
        else
        {
            if (rs.RequestData.Length > 1)
            {
                // 所有数据都已被读取,因此将其显示到控制台
                string strContent;
                strContent = rs.RequestData.ToString();
                Console.WriteLine(strContent);
            }

            // 关闭响应流
            responseStream.Close();

            // 设置 ManualResetEvent,以便主线程可以退出
            allDone.Set();
        }
        return;
    }
}

 

在这里有回调函数,且异步回调中又有异步操作。

首先是异步获得ResponseStream,然后异步读取数据。

这个程序非常经典。从中可以学到很多东西的。我们来共同探讨。

 
总结

上面说过,.net framework 可以异步调用任何方法。所以异步用处广泛。

在.net framework 类库中也有很多异步调用的方法。一般都是已Begin开头End结尾构成一对,异步委托方法,外加两个回调函数和AsyncState参数,组成异步操作的宏观体现。所以要做异步编程,不要忘了委托delegate、Begin,End,AsyncCallBack委托,AsyncState实例(在回调函数中通过IAsyncResult.AsyncState来强制转换),IAsycResult(监控异步),就足以理解异步真谛了。

复制链接 网友评论 收藏本文 关闭此页
上一条: XPath路径表达式学习总结-HtmlAgi…  下一条: C#如何设置KeepAlive
夜鹰教程网成立于2008年,目前已经运营了将近 13 年,发布了大量关于 html5/css3/C#/asp.net/java/python/nodejs/mongodb/sql server/android/javascript/mysql/mvc/easyui/vue/echarts原创教程。 我们一直都在坚持的是:认证负责、一丝不苟、以工匠的精神来打磨每一套教程,让读者感受到作者的用心。我们默默投入的时间,确保每一套教程都是一件作品,而不是呆板的文字和视频! 目前我们推出在线辅导班试运营,模式为一对一辅导,教学工具为QQ。我们的辅导学科包括 java 、android原生开发、webapp开发、商城开发、C#和asp.net开发,winform和物联网开发、web前端开发,但不仅限于此。 普通班针对的是国内学员,例如想打好基础的大学生、想转行的有志青年、想深入学习的程序员、想开发软件的初学者或者业余爱好者等。 就业办针对即将毕业上岗的大四学生,或者打算转行的初级开发工程师。 留学生班针对的是在欧美、加拿大、澳洲、日本、韩国、新加坡等地留学的中国学子,目的是让大家熟练地掌握编程技能,按时完成老师布置的作业,并能顺利地通过考试。 详细咨询QQ:1416759661   夜鹰教程网  基于角色的权限管理系统(c-s/b-s)。
  夜鹰教程网  基于nodejs的聊天室开发视频教程
  夜鹰教程网  Git分布式版本管理视频教程
  夜鹰教程网  MVC+EasyUI视频教程
  夜鹰教程网  在线考试系统视频教程
  夜鹰教程网  MongoDB视频教程。
  夜鹰教程网 Canvas视频教程
  夜鹰教程网 报表开发视频教程
  推荐教程/优惠活动

  热门服务/教程目录

  夜鹰教程网  新手必看,详细又全面。
  夜鹰教程网  购买教程  夜鹰教程网  在线支付-方便
  夜鹰教程网  担保交易-快捷安全   夜鹰教程网  闪电发货
  夜鹰教程网  电话和QQ随时可以联系我们。
  夜鹰教程网 不会的功能都可以找我们,按工作量收费。

客服电话:153 9760 0032

购买教程QQ:1416759661  
  热点推荐
在Windows系统下搭建SVN服务器
宽带连接速度慢
在iis下设置伪静态的规则和方法
Oralce 9i安装OID目录服务器说明
需要停止的windows 2003 server服…
.htaccess文件设置技巧16则
Apache SSL证书安装指南
linux下手工修改分区后的挂载
MSN服务器为什么不放置在中国境内…
自定义MIME类型 网络空间支持FLV
稳定的国外网站服务器对SEO排名没…
Windows下定期自动备份网站软件—…
实战讲解:从零开始配置Linux服务器…
IIS错误代码及其含义
服务器领域众“菜鸟”们的几个常见…
  尊贵服务
夜鹰教程网 承接业务:软件开发 网站开发 网页设计 .Net+C#+VS2008+MSsql+Jquery+ExtJs全套高清完整版视频教程
  最近更新
nodejs文件上传代码
nodejs如何设置允许跨域请求
npm 项目更换目录后无法启动
Git常用命令学习
Node.js 连接 MongoDB
Node.js JXcore 打包
Node.js 多进程详解
Node.js RESTful API
Node.js Express 框架 文件上传等…
Node.js Web 模块
Node.js 工具模块
Node.js GET/POST请求
Node.js 文件系统
Node.js 常用工具函数
Node.js 全局对象
  工具下载  需要远程协助? 

sql2008视频教程 c#视频教程

VIP服务:如果您的某个功能不会做,可以加我们QQ,给你做DEMO!

JQUERY  Asp.net教程

MVC视频教程  vs2012
.NET+sql开发
手机:15397600032 C#视频教程下载
微信小程序 vue.js高级实例视频教程

教程咨询QQ:1416759661


这篇文章不能解决你的问题?我们还有相关视频教程云课堂 全套前端开发工程师培训课程

微信号:yyjcw10000 QQ:1416759661  远程协助需要加QQ!

业务范围:视频教程|程序开发|在线解答|Demo制作|远程调试| 点击查看相关的视频教程

技术范围:全端开发/前端开发/webapp/web服务/接口开发/单片机/C#/java/node/sql server/mysql/mongodb/android/。 



关于我们 | 购买教程 | 网站建设 | 技术辅导 | 常见问题 | 联系我们 | 友情链接

夜鹰教程网 版权所有 www.yyjcw.com All rights reserved 备案号:蜀ICP备08011740号3