文档章节

5.4 异步TCP编程(三)

张金富
 张金富
发布于 2012/07/09 19:03
字数 1088
阅读 280
收藏 2
点赞 0
评论 0

    5.4.3 使用异步方式调用同步方法

    .NET Framework提供了一种可以利用委托异步调用任何方法的技术,唯一的要求就是需要声明一个与要调用的方法具有相同签名的委托。对于任何一个方法,如果希望异步执行,最简单的方法就是通过调用委托的BeginInvoke方法开始异步执行,然后执行其他操作,最后调用委托的EndInvoke方法结束异步操作。由于EndInvoke直到异步操作完成后才返回,因此这种方法非常适合文件或网络操作。


    1、声明与要调用的方法具有相同签名的委托

    下面的代码说明了如何声明一个与要调用的方法具有相同签名的委托:

private BinaryReader br;
...
delegate void SendMessageDelegate(string message);
private void SendMessage(string message)
{
	try
	{
		bw.write(message);
		bw.flush();
	}
	catch
	{
		MessageBox.Show("发送失败!");
	}
}

    2、通过轮询方式检查异步调用是否完成

    声明和SendMessage方法具有相同签名的委托以后,公共语言运行时就会自动为该委托定义BeginInvoke方法和EndInvoke方法。然后就可以异步调用SendMessage方法了。

    调用BeginInvoke方法后,该方法会立即返回IAsyncResult类型的接口,从用户界面的服务线程中进行异步调用时,可以利用该接口的IsCompleted属性来通过轮询方式检查异步调用是否完成。在轮询过程中,BeginInvoke方法在ThreadPool中创建的线程会继续执行异步方法。例如:

private bool needExit;
...
SendMessageDelegate d = new SendMessageDelegate(SendMessage);
IAsyncResult result = d.BeginInvoke(message, null, null);
while(result.IsCompleted == false)
{
    if(needExit)
    {
        break;
    }
    Thread.Sleep(50);
}

    当然,代码中只是演示了调用BeginInvoke后,如何查询异步操作是否完成,实际上也可以在调用BeginInvoke后,执行其他任何代码。

    BeginInvoke方法除了与要异步执行的方法具有相同的参数外,另外还有两个可选参数,第1个参数是一个AsyncCallback委托,该委托引用在异步调用完成时要调用的方法;第2个参数是一个用户定义的对象,该对象将消息传入回调方法。在这段代码中,由于用不到这两个参数,所以全部将其设置为null。

    程序调用BeginInvoke后,会立即返回一个可用于监视异步调用进度的IAsyncResult 接口,并继续执行BeginInvoke方法后面的代码,而不是等待异步调用完成。

    3、使用EndInvoke结束异步调用

    EndInvoke方法用于检索异步调用的结果,并结束异步调用。调用BeginInvoke之后,随时可以调用该方法。如果异步调用尚未完成,则EndInvoke会一直阻止该调用线程,直到异步调用完成。例如,在退出轮询后,可以直接通过下面的代码结束异步调用:

d.EndInvoke(result);

    与其他异步操作的End方法相同,调用EndInvoke方法后,在EndInvoke方法返回前,由于有可能会引起调用EndInvoke方法的线程阻塞,所以一般不要从服务于用户界面的线程直接调用该方法,否则会在异步操作完成前,给用户一个界面无反应的错觉。为了使界面操作流畅,可以将上面的语句该为用其它线程执行,例如:

private struct SendMessageStates
{
    public SendMessageDelagate d;
    public IAsyncResult result;
}
private void AsyncSendMessage(string message)
{
    SendMessageDelagate d = new SendMessageDelagate(SendMessage);
    IAsyncResult result = d.BeginInvoke(message, null, null);
    while(result.IsCompleted == false)
    {
        Thread.Sleep(50);
    }
    SendMessageStates states = new SendMessageStates();
    states.d = d;
    states.result = result;
    Thread t = new Thread(FinishAsyncSendMessage);
    t.IsBackground = true;
    t.Start(states);
}
private void FinishAsyncSendMessage(object obj)
{
    SendMessageStates states = (SendMessageStates)obj;
    states.d.EndInvoke(states.result);
}

    4、在异步调用中传递多个参数

    在异步调用中,如果有多个参数信息,这些参数还可以使用out和ref关键字。例如:

delegate void ReceiveMessageDelegate(out string receiveMessage);
private void ReceiveMessage(out string receiveMessage)
{
    receiveMessage = null;
    try
    {
        receiveMessage = br.ReadString();
    }
    catch(Exception ex)
    {
        MessageBox.Show(ex.message);
    }
}
...
ReceiveMessageDelegate d = new ReceiveMessageDelegate(ReceiveMessage);
IAsyncResult result = d.BeginInvoke(out receiveString, null, null);
while(result.IsCompleted == false)
{
    Thread.Sleep(250);
}
d.EndInvoke(out receiveString, result);

    可见,使用异步方式调用同步方法,既实现了任何方法的异步调用,又可以轻而易举地解决异步调用中的同步问题,对于相对比较复杂的异步处理过程,这是首选的方法,也是最简单、最方便的方法。

本文转载自:

共有 人打赏支持
张金富
粉丝 54
博文 6
码字总数 95
作品 0
烟台
程序员
5.4 异步TCP编程(二)

5.4.2 异步TCP应用编程的一般方法(本节可以忽略) 使用异步TCP编程时,除了套接字有对应的异步操作方式外,TcpListener和TcpClient类均提供了返回结果为IAsyncResult类型的异步操作的方法。...

张金富 ⋅ 2012/07/07 ⋅ 0

C#网络编程系列文章(一)之Socket实现异步TCP服务器

原创性声明 本文作者:小竹zz 本文地址http://blog.csdn.net/zhujunxxxxx/article/details/44258719 转载请注明出处 文章系列目录 C#网络编程系列文章(一)之Socket实现异步TCP服务器 C#网络编...

zhujunxxxxx ⋅ 2015/03/14 ⋅ 0

C#网络编程系列文章(二)之Socket实现同步TCP服务器

原创性声明 本文作者:小竹zz 本文地址http://blog.csdn.net/zhujunxxxxx/article/details/44258719 转载请注明出处 文章系列目录 C#网络编程系列文章(一)之Socket实现异步TCP服务器 C#网络编...

zhujunxxxxx ⋅ 2015/03/14 ⋅ 0

C#网络编程系列文章(三)之TcpListener实现异步TCP服务器

原创性声明 本文作者:小竹zz 本文地址http://blog.csdn.net/zhujunxxxxx/article/details/44258719 转载请注明出处 文章系列目录 C#网络编程系列文章(一)之Socket实现异步TCP服务器 C#网络编...

zhujunxxxxx ⋅ 2015/03/14 ⋅ 0

C#网络编程系列文章(四)之TcpListener实现同步TCP服务器

原创性声明 本文作者:小竹zz 本文地址http://blog.csdn.net/zhujunxxxxx/article/details/44258719 转载请注明出处 文章系列目录 C#网络编程系列文章(一)之Socket实现异步TCP服务器 C#网络编...

zhujunxxxxx ⋅ 2015/03/15 ⋅ 0

C#网络编程系列文章(七)之UdpClient实现异步UDP服务器

原创性声明 本文作者:小竹zz 本文地址http://blog.csdn.net/zhujunxxxxx/article/details/44258719 转载请注明出处 文章系列目录 C#网络编程系列文章(一)之Socket实现异步TCP服务器 C#网络编...

zhujunxxxxx ⋅ 2015/03/16 ⋅ 0

花花世界欢乐多/swoole-worker

swoole-worker 关于本项目 此项目是workerman(v3.4.5)的swoole移植版本,移除了对pcntl,libevent,event,ev扩展的依赖,转而使用swoole提供的swooleprocess和swooleevent,定时器采用swoole的s...

花花世界欢乐多 ⋅ 2017/08/15 ⋅ 0

C#网络编程系列文章(五)之Socket实现异步UDP服务器

原创性声明 本文作者:小竹zz 本文地址http://blog.csdn.net/zhujunxxxxx/article/details/44258719 转载请注明出处 文章系列目录 C#网络编程系列文章(一)之Socket实现异步TCP服务器 C#网络编...

zhujunxxxxx ⋅ 2015/03/15 ⋅ 0

C#网络编程系列文章(八)之UdpClient实现同步UDP服务器

原创性声明 本文作者:小竹zz 本文地址http://blog.csdn.net/zhujunxxxxx/article/details/44258719 转载请注明出处 文章系列目录 C#网络编程系列文章(一)之Socket实现异步TCP服务器 C#网络编...

zhujunxxxxx ⋅ 2015/03/16 ⋅ 0

C#网络编程系列文章(六)之Socket实现同步UDP服务器

原创性声明 本文作者:小竹zz 本文地址http://blog.csdn.net/zhujunxxxxx/article/details/44258719 转载请注明出处 文章系列目录 C#网络编程系列文章(一)之Socket实现异步TCP服务器 C#网络编...

zhujunxxxxx ⋅ 2015/03/16 ⋅ 0

没有更多内容

加载失败,请刷新页面

加载更多

下一页

vuex学习

1、getters基本用法: 在store.js里面用const声明我们的getters属性。 const getters={ count:function (state) { return state.count +=100; }} export default new Vuex.S......

大美琴 ⋅ 32分钟前 ⋅ 0

292. Nim Game - LeetCode

Question 292. Nim Game Solution 思路:试着列举一下,就能发现一个n只要不是4的倍数,就能赢。 n 是否能赢1 true2 true3 true4 false 不论删除几,对方都能一把赢5 t...

yysue ⋅ 44分钟前 ⋅ 0

G6 关系数据可视化图形库 简单使用

官网 https://antv.alipay.com/zh-cn/g6/1.x/index.html 效果 首先生成给定数目的小球,并设置随机的颜色 按照顺序,设置小球的角度以及坐标 设置定时器,每隔一定的时间修改小球的角度和坐标...

阿豪boy ⋅ 46分钟前 ⋅ 0

6.5 zip压缩工具 6.6 tar打包 6.7 打包并压缩

zip压缩工具 zip命令可以压缩目录和文件,-r 压缩目录。 zip使用方法 zip 1.txt.zip 1.txt //压缩文件 zip -r 123.zip 123/ //压缩目录 unzip 1.txt.zip //解压 unzip 123.zip -d /root/456...

Linux_老吴 ⋅ 55分钟前 ⋅ 0

react-loadable使用跳坑

官方给react-loadable的定义是: A higher order component for loading components with dynamic imports. 动态路由示例 withLoadable.js import React from 'react'import Loadable fro......

pengqinmm ⋅ 今天 ⋅ 0

记录工作中遇到的坑

1、ios safari浏览器向下滚动会触发window resize事件

端木遗风 ⋅ 今天 ⋅ 0

桥接设计模式

1、概述: 将抽象部分与他的实现部分分离,这样抽象化与实现化解耦,使他们可以独立的变化 如何实现解耦的呢,就是通过提供抽象化和实现化之间的桥接结构 桥接模式将继承模式转化成关联关系,他降...

职业搬砖20年 ⋅ 今天 ⋅ 0

20.zip压缩 tar打包 打包并压缩

6月25日任务 6.5 zip压缩工具 6.6 tar打包 6.7 打包并压缩 6.5 zip压缩工具: zip支持压缩目录 zip压缩完之后原来的文件不删除 不同的文件内容其实压缩的效果不一样 文件内有很多重复的用xz压...

王鑫linux ⋅ 今天 ⋅ 0

double类型数据保留四位小数的另一种思路

来源:透析公式处理,有时候数据有很长的小数位,有的时候由在四位以内,如果用一般的处理方法,那么不足四位的小树会补充0到第四位,这样子有点画蛇添足的感觉,不太好看。所以要根据小数的...

young_chen ⋅ 今天 ⋅ 0

Django配置163邮箱出现 authentication failed(535)错误解决方法

最近用Django写某网站,当配置163邮箱设置完成后,出现535错误即:smtplib.SMTPAuthenticationError: (535, b'Error: authentication failed') Django初始配置邮箱设置 EMAIL_HOST = "smtp.1...

陈墨轩_CJX ⋅ 今天 ⋅ 0

没有更多内容

加载失败,请刷新页面

加载更多

下一页

返回顶部
顶部