• 异步调用结果的获取(转)


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

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

    关于异步调用及返回值的获取,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 { getprivate set; }
            
    public bool Ready { getprivate 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

     

  • 相关阅读:
    线性规划学习笔记
    函数案例练习(python练习):设计一个简单的人员管理系统
    Python selenium Chrome正在受到自动软件的控制 disableinfobars无效 的解决方法
    IIS、apache、nginx日志中如何获取用户的真实IP?
    采用云计算轻松实现多人同时编辑在线思维导图
    成功加入BizSpark
    鹰翔MindV在线思维导图软件寒假期间开放个人版功能
    在线思维导图软件MindV收录在Windows azure marketplace
    写博客免费使用在线思维导图软件MindV个人版
    祝贺MindV进入香港国际软件大奖赛100强
  • 原文地址:https://www.cnblogs.com/wangshuai/p/1760017.html
Copyright © 2020-2023  润新知