文档章节

5.4 异步TCP编程(三)

张金富
 张金富
发布于 2012/07/09 19:03
字数 1088
阅读 284
收藏 2

    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);

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

本文转载自:

共有 人打赏支持
张金富
粉丝 55
博文 9
码字总数 5858
作品 0
烟台
程序员
私信 提问
C#网络编程系列文章(一)之Socket实现异步TCP服务器

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

zhujunxxxxx
2015/03/14
0
0
C#网络编程系列文章(二)之Socket实现同步TCP服务器

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

zhujunxxxxx
2015/03/14
0
0
花花世界欢乐多/swoole-worker

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

花花世界欢乐多
2017/08/15
0
0
C#网络编程系列文章(三)之TcpListener实现异步TCP服务器

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

zhujunxxxxx
2015/03/14
0
0
C#网络编程系列文章(七)之UdpClient实现异步UDP服务器

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

zhujunxxxxx
2015/03/16
0
0

没有更多内容

加载失败,请刷新页面

加载更多

开发者和架构师之间最大的区别是什么?

1、开发者和架构师之间最大的区别是什么? 架构师和开发者一样,也经常写代码,简单的说,开发者和架构师之间最大的区别就是技术领导力。 软件架构师的角色需要理解最重要的架构驱动力是什么...

James-
15分钟前
0
0
java框架学习日志-4

补充一些spring配置文件的方法。 设置别名: <!--通过name直接设置别名--> <bean name="user2" class="cn.sxt.factory.UserDynamicFactory"> </bean> <!--有id的情况下也可以设置......

白话
18分钟前
0
0
20181213 上课截图

小丑鱼00
34分钟前
1
0
nginx+php-fpm配置后页面显示空白的解决方法以及用nginx和php-fpm解决“502 Bad Gateway”问题

https://stackoverflow.com/questions/15423500/nginx-showing-blank-php-pages For reference, I am attaching my location block for catching files with the .php extension: location ~......

Yao--靠自己
41分钟前
2
0
mac 没声音

somehow不时就会出现这种情况。之前都得重启。 其实可以直接在terminal里打以下命令: sudo kextunload /System/Library/Extensions/AppleHDA.kext sudo kextload /System/Library/Extension...

dubox
57分钟前
1
0

没有更多内容

加载失败,请刷新页面

加载更多

返回顶部
顶部