异步调用结果的获取(转)
很多时候,为了获得更好的响应速度和并发性时,我们采用主动对象(线程池)的模式来实现对函数的执行。
这样做一个不便之处在于:函数调用者并不是函数的执行者,调用者并不知道何时函数执行完成。特别是有的时候,函数的调用者需要根据函数的返回值来决定下一步的操作,这个时候就需要一种机制来获取函数的返回值。
关于异步调用及返回值的获取,C#本身的委托异步调用是一种非常完善的异步机制。然而有时不能适合如我们的需要,这里从底层开始简单的实现自己的异步机制,可以有一个更清楚的认识和学习,并且和C#提供的语法糖无关,可以移植到各种其它语言中去。
异步调用的返回值的获取方式有两种:同步获取和异步获取。
异步获取:
异步获取非常简单,函数调用者在对执行者添加函数任务时,同时注册一个回调函数。函数执行者执行玩函数后,执行回调函数,返回值通过回调函数的参数带回。
同步获取:
异步获取的方式获取的返回值是在执行者的线程返回,而不是在调用者的线程中,使用起来不是很方便,同步调用则可以解决这个问题
同步调用主要分为以下几个步骤。
函数调用者添加函数执行任务后,阻塞当前线程。
函数执行者执行完函数后,将返回值放在和调用者约定的位置,并通知函数调用者线程。
函数调用者接收到通知后,停止阻塞线程,通过约定的位置获取返回值,继续执行。
PS:其实通过这种方式从效率上和复杂性来讲,不如直接调用函数来得方便。这种方式一般在如下几种情况下使用:
函数只能通过异步方式执行,而为了程序逻辑简单,需要用同步方式获取。
函数调用虽然非常耗时,但只在很少的情况下需要用同步的方式获取返回值,这时使用异步调用仍能节省许多时间。
两种获取返回值方式的比较:
同步获取逻辑上比较简单。
异步获取效率较高。
每种方式的优点是对方的缺电,两种方式互为补充,可根据具体情况适当使用,甚至一起使用,
实现:
异步调用的实现非常简单,特别是在C#支持lamabda表达式之后,可以以一种非常优雅的方式封装函数,获取返回值,这里就不介绍了。
同步调用的一种简单的实现如下:
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading;
namespace ConsoleApplication1
{
class Program
{
static void Main(string[] args)
{
Future<string> f = new Future<string>(Foo);
ThreadPool.QueueUserWorkItem(x => { Thread.Sleep(3 * 1000); f.Excute(); });
//ThreadPool.QueueUserWorkItem(x => f.Excute());
Thread.Sleep(1000);
Console.WriteLine("waitting answer...");
//f.Wait();
//Console.WriteLine("answer:\t" + f.Value);
if (f.Wait(TimeSpan.FromSeconds(5)))
Console.WriteLine("answer:\t" + f.Value);
else
Console.WriteLine("time out");
Console.WriteLine("test finished");
Thread.Sleep(-1);
}
static string Foo()
{
Console.WriteLine("foo begin");
string s = Console.ReadLine();
Console.WriteLine("foo finished.");
return s;
}
}
delegate T ExcuteHanlder<T>();
class Future<T>
{
public T Value { get; private set; }
public bool Ready { get; private set; }
ExcuteHanlder<T> function;
public Future(ExcuteHanlder<T> function)
{
this.function = function;
}
public void Excute()
{
Value = function();
lock (this)
{
Ready = true;
Monitor.Pulse(this);
}
}
public bool Wait()
{
return Wait(TimeSpan.Zero);
}
public bool Wait(TimeSpan timeout)
{
lock (this)
{
if (!Ready)
{
if (timeout == TimeSpan.Zero)
return Monitor.Wait(this);
else
return Monitor.Wait(this, timeout);
}
}
return true;
}
}
}
原文链接:http://www.gispower.org/article/dev/2008/93/0893102215A2HJK4A1F54G1J9EH668.html
转载于:https://www.cnblogs.com/wangshuai/archive/2010/06/18/1760017.html
异步调用结果的获取(转)相关推荐
- springboot 多线程_SpringBoot异步调用@Async
一. 什么是异步调用? 异步调用是相对于同步调用而言的,同步调用是指程序按预定顺序一步步执行,每一步必须等到上一步执行完后才能执行,异步调用则无需等待上一步程序执行完即可执行. 二. 如何实现异步调用 ...
- C++多线程:package_task异步调用任何目标执行操作
文章目录 描述 函数成员及使用 总结 我们上一篇描述关于C++多线程中的异步操作相关库( async和 promise),本节将分享c++标准库中最后一个多线程异步操作库 package_task的学 ...
- springboot之异步调用@Async
引言: 在Java应用中,绝大多数情况下都是通过同步的方式来实现交互处理的:但是在处理与第三方系统交互的时候,容易造成响应迟缓的情况,之前大部分都是使用多线程来完成此类任务,其实,在spring 3. ...
- Spring Boot 中使用@Async实现异步调用,加速任务执行!
欢迎关注方志朋的博客,回复"666"获面试宝典 什么是"异步调用"?"异步调用"对应的是"同步调用",同步调用指程序按照 ...
- Spring Boot 异步请求和异步调用
点击上方"方志朋",选择"设为星标" 回复"666"获取新整理的面试文章 一.Spring Boot中异步请求的使用 1.异步请求与同步请求 ...
- JavaScript异步调用的发展历程
同步与异步 通常,代码是由上而下依次执行的.如果有多个任务,就必须排队,前一个任务完成,后一个任务才能执行.这种连续的执行模式就叫做同步. a(); b(); c(); 复制代码 上面代码中,a.b. ...
- Dubbo 同步、异步调用的几种方式
我们知道,Dubbo 缺省协议采用单一长连接,底层实现是 Netty 的 NIO 异步通讯机制:基于这种机制,Dubbo 实现了以下几种调用方式: 同步调用 异步调用 参数回调 事件通知 同步调用 同 ...
- 17委托异步调用方法
抽象出一个炒菜的类. 1: //炒菜 2: public class Cooking 3: { 4: public string Cook(string food1, string food2) 5: ...
- 如何从异步调用返回响应?
我有一个函数foo ,它发出Ajax请求. 如何返回foo的响应? 我尝试从success回调中返回值,以及将响应分配给函数内部的局部变量并返回该局部变量,但这些方法均未真正返回响应. functio ...
最新文章
- 如何处理单元测试产生的数据,下列哪些说法是正确的
- 设置Kali Linux永不锁屏
- 生成jpg的缩略图并添加水印
- jsp mysql 注入攻击实例
- 计算Be原子基态能级
- django redirect传递参数_Django中间件
- Confluence 6 考虑使用自定义 CSS
- java porm.xml_通过Maven仓库安装Spire.PDF for Java
- linux新终端找回任务,Linux 终端任务后台执行
- Linux select 一网打尽
- Ueberschall Elastik 3 for Mac - 弹性Loops音源采样器
- k8s认证及ServiceAccount-十五
- 什么是 SAP BAPI
- something just歌词用计算机,Something Just Like This歌词翻译
- php chm中文手册201502月更新
- 青春期的我们……妥协…挣扎…惊醒
- EasyClick adb shell命令大全
- 前端程序调试方法总结--高级版
- 黑石裸金属服务器是什么?有什么产品优势?
- 详细解读大数据分析学习路线