很多时候,为了获得更好的响应速度和并发性时,我们采用主动对象(线程池)的模式来实现对函数的执行。

这样做一个不便之处在于:函数调用者并不是函数的执行者,调用者并不知道何时函数执行完成。特别是有的时候,函数的调用者需要根据函数的返回值来决定下一步的操作,这个时候就需要一种机制来获取函数的返回值。

关于异步调用及返回值的获取,C#本身的委托异步调用是一种非常完善的异步机制。然而有时不能适合如我们的需要,这里从底层开始简单的实现自己的异步机制,可以有一个更清楚的认识和学习,并且和C#提供的语法糖无关,可以移植到各种其它语言中去。

异步调用的返回值的获取方式有两种:同步获取和异步获取。

异步获取:

异步获取非常简单,函数调用者在对执行者添加函数任务时,同时注册一个回调函数。函数执行者执行玩函数后,执行回调函数,返回值通过回调函数的参数带回。

同步获取:

异步获取的方式获取的返回值是在执行者的线程返回,而不是在调用者的线程中,使用起来不是很方便,同步调用则可以解决这个问题

同步调用主要分为以下几个步骤。

函数调用者添加函数执行任务后,阻塞当前线程。
函数执行者执行完函数后,将返回值放在和调用者约定的位置,并通知函数调用者线程。
函数调用者接收到通知后,停止阻塞线程,通过约定的位置获取返回值,继续执行。
PS:其实通过这种方式从效率上和复杂性来讲,不如直接调用函数来得方便。这种方式一般在如下几种情况下使用:

函数只能通过异步方式执行,而为了程序逻辑简单,需要用同步方式获取。
函数调用虽然非常耗时,但只在很少的情况下需要用同步的方式获取返回值,这时使用异步调用仍能节省许多时间。
两种获取返回值方式的比较:

同步获取逻辑上比较简单。
异步获取效率较高。
每种方式的优点是对方的缺电,两种方式互为补充,可根据具体情况适当使用,甚至一起使用,

实现:

异步调用的实现非常简单,特别是在C#支持lamabda表达式之后,可以以一种非常优雅的方式封装函数,获取返回值,这里就不介绍了。

同步调用的一种简单的实现如下:

using System;
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

异步调用结果的获取(转)相关推荐

  1. springboot 多线程_SpringBoot异步调用@Async

    一. 什么是异步调用? 异步调用是相对于同步调用而言的,同步调用是指程序按预定顺序一步步执行,每一步必须等到上一步执行完后才能执行,异步调用则无需等待上一步程序执行完即可执行. 二. 如何实现异步调用 ...

  2. C++多线程:package_task异步调用任何目标执行操作

    文章目录 描述 函数成员及使用 总结 我们上一篇描述关于C++多线程中的异步操作相关库( async和 promise),本节将分享c++标准库中最后一个多线程异步操作库 package_task的学 ...

  3. springboot之异步调用@Async

    引言: 在Java应用中,绝大多数情况下都是通过同步的方式来实现交互处理的:但是在处理与第三方系统交互的时候,容易造成响应迟缓的情况,之前大部分都是使用多线程来完成此类任务,其实,在spring 3. ...

  4. Spring Boot 中使用@Async实现异步调用,加速任务执行!

    欢迎关注方志朋的博客,回复"666"获面试宝典 什么是"异步调用"?"异步调用"对应的是"同步调用",同步调用指程序按照 ...

  5. Spring Boot 异步请求和异步调用

    点击上方"方志朋",选择"设为星标" 回复"666"获取新整理的面试文章 一.Spring Boot中异步请求的使用 1.异步请求与同步请求 ...

  6. JavaScript异步调用的发展历程

    同步与异步 通常,代码是由上而下依次执行的.如果有多个任务,就必须排队,前一个任务完成,后一个任务才能执行.这种连续的执行模式就叫做同步. a(); b(); c(); 复制代码 上面代码中,a.b. ...

  7. Dubbo 同步、异步调用的几种方式

    我们知道,Dubbo 缺省协议采用单一长连接,底层实现是 Netty 的 NIO 异步通讯机制:基于这种机制,Dubbo 实现了以下几种调用方式: 同步调用 异步调用 参数回调 事件通知 同步调用 同 ...

  8. 17委托异步调用方法

    抽象出一个炒菜的类. 1: //炒菜 2: public class Cooking 3: { 4: public string Cook(string food1, string food2) 5: ...

  9. 如何从异步调用返回响应?

    我有一个函数foo ,它发出Ajax请求. 如何返回foo的响应? 我尝试从success回调中返回值,以及将响应分配给函数内部的局部变量并返回该局部变量,但这些方法均未真正返回响应. functio ...

最新文章

  1. 如何处理单元测试产生的数据,下列哪些说法是正确的
  2. 设置Kali Linux永不锁屏
  3. 生成jpg的缩略图并添加水印
  4. jsp mysql 注入攻击实例
  5. 计算Be原子基态能级
  6. django redirect传递参数_Django中间件
  7. Confluence 6 考虑使用自定义 CSS
  8. java porm.xml_通过Maven仓库安装Spire.PDF for Java
  9. linux新终端找回任务,Linux 终端任务后台执行
  10. Linux select 一网打尽
  11. Ueberschall Elastik 3 for Mac - 弹性Loops音源采样器
  12. k8s认证及ServiceAccount-十五
  13. 什么是 SAP BAPI
  14. something just歌词用计算机,Something Just Like This歌词翻译
  15. php chm中文手册201502月更新
  16. 青春期的我们……妥协…挣扎…惊醒
  17. EasyClick adb shell命令大全
  18. 前端程序调试方法总结--高级版
  19. 黑石裸金属服务器是什么?有什么产品优势?
  20. 详细解读大数据分析学习路线

热门文章

  1. 创业几乎不要本钱,是创业圈内最大的谎言
  2. c语言程序设计小学生测验,c语言程序设计(1) 小学生计算机辅助教学系统
  3. sql server 复制_SQL Server复制(合并)–复制什么,什么不复制
  4. CSS之cacl()函数
  5. node.js下npm安装太慢,如何解决
  6. LINUX 文件夹打包
  7. 第二百五十八天 how can I 坚持
  8. MVVM绑定多层级数据到TreeView并设置项目展开
  9. JDK1.5新特性介绍
  10. HTML5 tel make a phone call