文档章节

5.4 异步TCP编程(三)

张金富
 张金富
发布于 2012/07/09 19:03
字数 1088
阅读 281
收藏 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);

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

本文转载自:

共有 人打赏支持
张金富
粉丝 54
博文 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
C#网络编程系列文章(三)之TcpListener实现异步TCP服务器

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

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

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

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

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

zhujunxxxxx
2015/03/16
0
0

没有更多内容

加载失败,请刷新页面

加载更多

打包QML程序

1、windeployqt执行路径(D:\Qt\5.12.0\msvc2017_64\bin)加入到PATH中 2、使用Qt自带的命令行交互 Command 终端(Qt 5.12.0 64-bit for Desktop (MSVC 2017))切换到 Release 编译成功的exe...

渣渣曦
22分钟前
0
0
优秀互联网高级测试工程师应该具备的能力

概述 在之前写的互联网高级测试工程师至少具备的能力一文中,提到了测试工程师至少具备的能力,但是并没有提到优秀测试工程师应该具备的能力,下文简单的谈一谈。当然这些全部都是我的个人理...

Sam哥哥聊技术
26分钟前
1
0
webpack项目配置

前端工程化 前端工程化是根据业务特点,将前端开发流程规范化,标准化,它包括了开发流程、技术选型、代码规范、构建发布等等,用语提升前端工程师的开发效率和代码质量。 自动化构建工具 1、...

羊皮卷
28分钟前
0
0
Linux命令备忘录: jobs 显示Linux中的任务列表及任务状态命令

jobs命令用于显示Linux中的任务列表及任务状态,包括后台运行的任务。该命令可以显示任务号及其对应的进程号。其中,任务号是以普通用户的角度进行的,而进程号则是从系统管理员的角度来看的...

开元中国2015
今天
2
0
springboot Whitelabel Error Page(Not Found)解决方案

当出现上图图的错误时注意 报错信息 There was an unexpected error (type=Not Found, status=404). Not Found代表未访问到资源 解决方案:比较访问路径和代码的路径有没有写错 正确的访问路...

斩神魂
今天
2
0

没有更多内容

加载失败,请刷新页面

加载更多

返回顶部
顶部