• linkedu视频
  • 平面设计
  • 电脑入门
  • 操作系统
  • 办公应用
  • 电脑硬件
  • 动画设计
  • 3D设计
  • 网页设计
  • CAD设计
  • 影音处理
  • 数据库
  • 程序设计
  • 认证考试
  • 信息管理
  • 信息安全
菜单
linkedu.com
  • 网页制作
  • 数据库
  • 程序设计
  • 操作系统
  • CMS教程
  • 游戏攻略
  • 脚本语言
  • 平面设计
  • 软件教程
  • 网络安全
  • 电脑知识
  • 服务器
  • 视频教程
  • JavaScript
  • ASP.NET
  • PHP
  • 正则表达式
  • AJAX
  • JSP
  • ASP
  • Flex
  • XML
  • 编程技巧
  • Android
  • swift
  • C#教程
  • vb
  • vb.net
  • C语言
  • Java
  • Delphi
  • 易语言
  • vc/mfc
  • 嵌入式开发
  • 游戏开发
  • ios
  • 编程问答
  • 汇编语言
  • 微信小程序
  • 数据结构
  • OpenGL
  • 架构设计
  • qt
  • 微信公众号
您的位置:首页 > 程序设计 >C#教程 > C#基础之异步调用实例教程

C#基础之异步调用实例教程

作者: 字体:[增加 减小] 来源:互联网 时间:2017-05-28

通过本文主要向大家介绍了c#socket异步通信实例,c#异步编程,c#socket异步通信,c#异步,c#异步委托等相关知识,希望对您有所帮助,也希望大家支持linkedu.com www.linkedu.com

本文实例形式展示了C#中异步调用的实现方法,并对其原理进行了较为深入的分析,现以教程的方式分享给大家供大家参考之用。具体如下:

首先我们来看一个简单的例子:

小明在烧水,等水烧开以后,将开水灌入热水瓶,然后开始整理家务
小文在烧水,在烧水的过程中整理家务,等水烧开以后,放下手中的家务活,将开水灌入热水瓶,然后继续整理家务
这也是日常生活中很常见的情形,小文的办事效率明显要高于小明。从C#程序执行的角度考虑,小明使用的同步处理方式,而小文则使用的异步处理方式。

同步处理方式下,事务是按顺序一件一件处理的;而异步方式则是,将子操作从主操作中分离出来,主操作继续进行,子操作在完成处理的时候通知主操作。

在C#中,异步通过委托来完成。请看下面的例子:

class Program  
{  
  static TimeSpan Boil()  
  {  
    Console.WriteLine("水壶:开始烧水...");  
    Thread.Sleep(6000);  
    Console.WriteLine("水壶:水已经烧开了!");  
    return TimeSpan.MinValue;  
  }  
 
  delegate TimeSpan BoilingDelegate();  
 
  static void Main(string[] args)  
  {  
    Console.WriteLine("小文:将水壶放在炉子上");  
    BoilingDelegate d = new BoilingDelegate(Boil);  
    IAsyncResult result = d.BeginInvoke(BoilingFinishedCallback, null);  
    Console.WriteLine("小文:开始整理家务...");  
    for (int i = 0; i < 20; i++)  
    {  
      Console.WriteLine("小文:整理第{0}项家务...", i + 1);  
      Thread.Sleep(1000);  
    }  
  }  
 
  static void BoilingFinishedCallback(IAsyncResult result)  
  {  
    AsyncResult asyncResult = (AsyncResult)result;  
    BoilingDelegate del = (BoilingDelegate)asyncResult.AsyncDelegate;
    del.EndInvoke(result);
    Console.WriteLine("小文:将热水灌到热水瓶");  
    Console.WriteLine("小文:继续整理家务");   
  }  
}
</div>

上面的例子是一个最简单的异步调用的例子,没有对异步调用函数做任何参数传递以及返回值校验。这个例子反映了小文烧水的流程,首先小文将水壶放在炉子上,在定义好委托以后,就使用BeginInvoke方法开始异步调用,即让水壶开始烧水,于是小文便开始整理家务。水烧开后,C#的异步模型会触发由BeginInvoke方法所指定的回调函数,也就是水烧开后的处理逻辑由这个回调函数定义,此时小文将水灌入热水瓶并继续整理家务。

由此可见,在C#中实现异步调用其实并不复杂,首先创建一个异步处理函数,并针对其定义一个委托;然后在调用函数的时候,使用委托的BeginInvoke方法,指定在函数处理完成时的回调函数(如果不需要对完成事件做处理,可以给null值),并指定所需的参数(如果没有参数,也可以给null值);最后在回调函数中处理完成事件。

请注意上例回调函数中的EndInvoke调用,EndInvoke会使得调用线程阻塞,直到异步函数处理完成。显然,紧接在BeginInvoke后面的EndInvoke使用方式与同步调用等价。

EndInvoke调用的返回值也就是异步处理函数的返回值。我们把程序稍作修改,将Boil方法改成下面的形式:

static TimeSpan Boil()  
{  
  DateTime begin = DateTime.Now;  
  Console.WriteLine("水壶:开始烧水...");  
  Thread.Sleep(6000);  
  Console.WriteLine("水壶:水已经烧开了!");  
  return DateTime.Now - begin;  
}  
</div>

然后将BoilingFinishedCallback改成下面的形式:

static void BoilingFinishedCallback(IAsyncResult result)  
{  
  AsyncResult asyncResult = (AsyncResult)result;  
  BoilingDelegate del = (BoilingDelegate)asyncResult.AsyncDelegate;  
  Console.WriteLine("(烧水一共用去{0}时间)", del.EndInvoke(result));  
  Console.WriteLine("小文:将热水灌到热水瓶");  
  Console.WriteLine("小文:继续整理家务");  
}  
</div>

那么我们就可以在EndInvoke的时候,获得由Boil异步处理函数返回的时间值。事实上,如果定义的BoilingDelegate委托存在参数列表,那么我们也可以在BeginInvoke的时候,将所需的参数传给异步处理函数。BeginInvoke/EndInvoke函数的签名与定义它们的委托签名有关。

注意:在修改后的BoilingFinishedCallback方法中,为了得到委托实例以便获取异步处理函数的返回值,我们采用了下面的转换:

AsyncResult asyncResult = (AsyncResult)result;  
BoilingDelegate del = (BoilingDelegate)asyncResult.AsyncDelegate;  

</div>

这样才能获得调用异步处理函数的委托的实体。

.NET处理异步函数调用,事实上是通过线程来完成的。这个过程有以下几个特点:

1.异步函数由线程完成,这个线程是.NET线程池中的线程

2.通常情况下,.NET线程池拥有500个线程(当然这个数量可以设置),每当调用BeginInvoke开始异步处理时,异步处理函数就由线程池中的某个线程负责执行,而用户无法控制具体是由哪个线程负责执行

3.由于线程池中线程数量有限,因此当池中线程被完全占用时,新的调用请求将使函数不得不等待空余线程的出现。此时,程序的效率会有所影响。

为了验证这些特点,请看下面的程序:

class Program  
{  
  delegate void MethodInvoker();  
  static void Foo()  
  {  
    int intAvailableThreads, intAvailableIoAsynThreds;  
    ThreadPool.GetAvailableThreads(out intAvailableThreads, out intAvailableIoAsynThreds);  
    string strMessage = String.Format(@"Is Thread Pool: {0},  
    Thread Id: {1} Free Threads {2}",  
        Thread.CurrentThread.IsThreadPoolThread.ToString(),  
        Thread.CurrentThread.GetHashCode(),  
        intAvailableThreads);  
    Console.WriteLine(strMessage);  
    Thread.Sleep(10000);  
    return;  
  }  
 
  static void CallFoo()  
  {  
    MethodInvoker simpleDelegate = new MethodInvoker(Foo);  
    for (int i = 0; i < 15; i++)  
    {  
      simpleDelegate.BeginInvoke(null, null);  
    }  
  }  
  static void Main(string[] args)  
  {  
    ThreadPool.SetMaxThreads(10, 10);  
    CallFoo();  
    Console.ReadLine();  
  }  
}

</div>

这个程序在起始的时候将线程池中最大线程个数设置为10个,然后做15次异步调用,每个异步调用中都停留10秒钟当作处理本身所要消耗的时间。从程序的执行我们可以看到,当前10个异步调用完全开始以后,新的异步调用就会等待(注意:不是主线程在等待),直到线程池中有线程空闲出来。

希望本文所述对大家的C#程序设计有所帮助。

</div>
分享到:QQ空间新浪微博腾讯微博微信百度贴吧QQ好友复制网址打印

您可能想查找下面的文章:

  • C#使用系统方法发送异步邮件完整实例
  • C#异步委托调用实例分析
  • C#中异步Socket通信编程代码实例
  • C# Socket网络编程实例
  • C#基础之异步调用实例教程
  • C#之Socket操作类实例解析
  • C#同步、异步远程下载文件实例
  • C#同步和异步调用方法实例
  • 使用异步方式调用同步方法(实例详解)

相关文章

  • 2017-05-28给c#添加SetTimeout和SetInterval函数
  • 2017-05-28C#根据反射和特性实现ORM映射实例分析
  • 2017-05-28C#基于面向过程计算加权平均分的方法
  • 2017-05-28C#如何自动选择出系统中最合适的IP地址
  • 2017-05-28C#实现异步发送邮件的方法
  • 2017-05-28C#中的匿名方法实例解析
  • 2017-05-28WinForm中快捷键与组合按键的设置方法
  • 2017-05-28C#实现简单播放mp3的方法
  • 2017-05-28英语单词state与status的区别
  • 2017-05-28c#反射调用方法示例

文章分类

  • JavaScript
  • ASP.NET
  • PHP
  • 正则表达式
  • AJAX
  • JSP
  • ASP
  • Flex
  • XML
  • 编程技巧
  • Android
  • swift
  • C#教程
  • vb
  • vb.net
  • C语言
  • Java
  • Delphi
  • 易语言
  • vc/mfc
  • 嵌入式开发
  • 游戏开发
  • ios
  • 编程问答
  • 汇编语言
  • 微信小程序
  • 数据结构
  • OpenGL
  • 架构设计
  • qt
  • 微信公众号

最近更新的内容

    • C#不登录电脑启动程序
    • 基于c#用Socket做一个局域网聊天工具
    • C#将dll打包到程序中的具体实现
    • C#中单例的实现方法
    • C#泛型委托的用法实例分析
    • C#键值对容器的介绍
    • C#获取图片的后缀名解析
    • c# 空合并运算符“??”的使用详解
    • C#模板方法模式(Template Method Pattern)实例教程
    • 详解Winform里面的缓存使用

关于我们 - 联系我们 - 免责声明 - 网站地图

©2020-2025 All Rights Reserved. linkedu.com 版权所有