设置调用方法的超时时间

  在工作中,遇到这样一个需求,我要做一个业务,要验证一下现有的数据是否正确,但这个验证又不是必须的,只是说如果这里验证不通过,后面流程就可以不走了,但是如果这里没有验证到,后面也会有验证。也就是说不影响主流程,算得上是一个优化吧。比如我要查询一个东西,但是这个时间不能超过1秒。

  在网上查了一下,基本上都是异步执行,有两个线程来做。我查到有两种方法。

第一种 独立成一个类

  代码如下:

  (1)、FuncTimeOut类

    /// <summary>
    /// 超时设置类
    /// </summary>
    public class FuncTimeOut
    {
        /// <summary>
        /// 信号量
        /// </summary>
        private ManualResetEvent manu = new ManualResetEvent(false);

        /// <summary>
        /// 是否接受到信号
        /// </summary>
        private bool isgetSignal;

        /// <summary>
        /// 设置超时时间
        /// </summary>
        private int timeout;

        /// <summary>
        /// 要委托调用的方法的一个委托
        /// </summary>
        private Action<int> funcNeedRun;

        /// <summary>
        /// 构造函数
        /// </summary>
        /// <param name="action">委托</param>
        /// <param name="timeout">超时时间</param>
        public FuncTimeOut(Action<int> action, int timeout)
        {
            this.funcNeedRun = action;
            this.timeout = timeout;
        }

        /// <summary>
        /// 执行方法
        /// </summary>
        /// <param name="param">参数</param>
        public void Execute(int param)
        {
            Action<int> tempAction = this.CombineActionAndManuset;
            var r = tempAction.BeginInvoke(param, this.MyAsynCallback, null);
            this.isgetSignal = this.manu.WaitOne(this.timeout);
            if (this.isgetSignal == true)
            {
                Console.WriteLine("未超时.");
                Console.WriteLine("ThreadName:" + Thread.CurrentThread.Name);
            }
            else
            {
                Console.WriteLine("超时");
                Console.WriteLine("ThreadName:" + Thread.CurrentThread.Name);
            }
        }

        /// <summary>
        /// 回调函数
        /// </summary>
        /// <param name="ar">异步操作时的状态</param>
        private void MyAsynCallback(IAsyncResult ar)
        {
            if (this.isgetSignal == false)
            {
                Console.WriteLine(Thread.CurrentThread.Name + ",超时,放弃执行回调函数");
                Thread.CurrentThread.Abort();
            }
            else
            {
                Console.WriteLine(Thread.CurrentThread.Name + ",执行成功");
            }
        }

        /// <summary>
        /// 执行方法
        /// </summary>
        /// <param name="para">参数</param>
        private void CombineActionAndManuset(int para)
        {
            Thread.CurrentThread.Name = "subThread";
            this.funcNeedRun(para);
            this.manu.Set();
        }
    }

  (2)、测试代码

    /// <summary>
    /// Class Program
    /// </summary>
    public class Program
    {
        /// <summary>
        /// Defines the entry point of the application.
        /// </summary>
        /// <param name="args">The args.</param>
        public static void Main(string[] args)
        {
            TestFuncTimeOut();
            Console.Read();
        }

        #region FunTimeOut测试

        /// <summary>
        /// 测试超时设置操作
        /// </summary>
        private static void TestFuncTimeOut()
        {
            Console.WriteLine("start");
            Thread.CurrentThread.Name = "Main";
            FuncTimeOut ft = new FuncTimeOut(ComputeSum, 3000);
            ft.Execute(10); // 测试修改点
            Console.WriteLine("ThreadName:" + Thread.CurrentThread.Name);
            Console.WriteLine("end");
        }

        /// <summary>
        /// Does the STH.
        /// </summary>
        /// <param name="num">The num.</param>
        private static void ComputeSum(int num)
        {
            int sum = 0;
            for (int i = 0; i < num; i++)
            {
                Thread.Sleep(500);
                sum += i;
                Console.WriteLine(i + ":ThreadName:" + Thread.CurrentThread.Name);
            }

            Console.WriteLine("sum = " + sum);

            // return sum;
        }

        #endregion
   }

  (3)、执行结果

  a、超时的情况(上面的测试代码测出来的结果)

 1 start
 2 0:ThreadName:subThread
 3 1:ThreadName:subThread
 4 2:ThreadName:subThread
 5 3:ThreadName:subThread
 6 4:ThreadName:subThread
 7 超时
 8 ThreadName:Main
 9 ThreadName:Main
10 end
11 5:ThreadName:subThread
12 6:ThreadName:subThread
13 7:ThreadName:subThread
14 8:ThreadName:subThread
15 9:ThreadName:subThread
16 sum = 45
17 subThread,超时,放弃执行回调函数

  b、未超时的情况(将上述黄色部分的标示改为:ft.Execute(3);的结果)

 1 start
 2 0:ThreadName:subThread
 3 1:ThreadName:subThread
 4 2:ThreadName:subThread
 5 sum = 3
 6 未超时.
 7 ThreadName:Main
 8 ThreadName:Main
 9 end
10 subThread,执行成功

  (4)、总结

    从上面的结果可以看出:

    第一、有两个线程

    第二、无论是否超时,方法都会被执行完毕,如果超时,则不忘下执行回调函数,否则执行。

第二种 封装成一个方法

  (1)、源代码

        /// <summary>
        /// 连续整数求和【测试方法】
        /// </summary>
        /// <param name="num">个数</param>
        /// <returns>结果</returns>
        private static int ComputeSumResult(int num)
        {
            int sum = 0;
            for (int i = 0; i < num; i++)
            {
                Thread.Sleep(500);
                sum += i;
                Console.WriteLine(i + ",ThreadName:" + Thread.CurrentThread.Name);
            }

            return sum;
        }

        /// <summary>
        /// 超时方法调用
        /// </summary>
        /// <param name="func">要调用的方法</param>
        /// <param name="param">要调用方法的参数</param>
        /// <param name="timeoutMillisecondes">超时时间</param>
        /// <returns>结束</returns>
        private static int CallWithTimeOutFun(Func<int, int> func, int param, int timeoutMillisecondes)
        {
            Thread threadToKill = null;
            int sum = 0;
            Action wrappedAction = () =>
            {
                threadToKill = Thread.CurrentThread;
                threadToKill.Name = "threadToKill";
                sum = func(param);
            };
            IAsyncResult result = wrappedAction.BeginInvoke(null, null);
            if (result.AsyncWaitHandle.WaitOne(timeoutMillisecondes))
            {
                Console.WriteLine("ThreadName:" + Thread.CurrentThread.Name);
                wrappedAction.EndInvoke(result);
                Console.WriteLine("没有超时");
                Console.WriteLine("ThreadName:" + Thread.CurrentThread.Name);
                return sum;
            }
            else
            {
                Console.WriteLine("ThreadName:" + Thread.CurrentThread.Name);
                threadToKill.Abort();
                Console.WriteLine("超时");
                Console.WriteLine("ThreadName:" + Thread.CurrentThread.Name);
                return sum;
            }
        }

  (2)、测试代码

    /// <summary>
    /// Class Program
    /// </summary>
    public class Program
    {
        /// <summary>
        /// Defines the entry point of the application.
        /// </summary>
        /// <param name="args">The args.</param>
        public static void Main(string[] args)
        {
            Console.WriteLine("start");
            Thread.CurrentThread.Name = "Main";
            int result = CallWithTimeOutFun(ComputeSumResult, 10, 3000);// 测试需要修改的代码
            Console.WriteLine("ThreadName:" + Thread.CurrentThread.Name + ", 结果是:" + result);
            Console.WriteLine("end");
            Console.Read();
        }
   }

  (3)、测试结果

  a、超时情况

 1 start
 2 0,ThreadName:threadToKill
 3 1,ThreadName:threadToKill
 4 2,ThreadName:threadToKill
 5 3,ThreadName:threadToKill
 6 4,ThreadName:threadToKill
 7 ThreadName:Main
 8 超时
 9 ThreadName:Main
10 ThreadName:Main, 结果是:0
11 end

  b、不超时的情况(将上面测试需要修改的代码修改为:int result = CallWithTimeOutFun(ComputeSumResult, 3, 3000);// 测试需要修改的代码)

1 start
2 0,ThreadName:threadToKill
3 1,ThreadName:threadToKill
4 2,ThreadName:threadToKill
5 ThreadName:Main
6 没有超时
7 ThreadName:Main
8 ThreadName:Main, 结果是:3
9 end

  (4)、总结

  从上面的结果可以看出:

    第一、有两个线程

    第二、如果方法超时,则不会将被调用的方法执行完毕,可以看出,方法是执行了,但由于超时,结果是不对的。如果方法没有超时,结果为正确的。这与上面方法的区别在于,方法超时就不会继续执行了。

时间: 2024-12-26 16:30:39

设置调用方法的超时时间的相关文章

帝国cms文章内容tags关键词设置调用方法以及tags静态化

说实话帝国cms用起来真的不好找一些功能,就比如说帝国cms的tag标签调用.需要注意的是帝国CMS文章的关键词和tags标签并非一码事,关键词标签是设置文章的关键词的,是用来给搜索引擎说明本篇文章的大意,而tags标签是用来链接文章的,对于SEOer来说,使用tags可以起到聚合的作用,增加网站页面,提高权重.那么帝国CMS如何调用当前文章内容tags以及实现tags静态化呢? 帝国CMS tags标签怎么设置: 1.登录后台,单击[栏目]菜单——[TAGS管理]——[设置TAGS参数]子菜单

设置mysql 事务锁超时时间 innodb_lock_wait_timeout

Mysql数据库采用InnoDB模式,默认参数:innodb_lock_wait_timeout设置锁等待的时间是50s,一旦数据库锁超过这个时间就会报错. mysql> SHOW GLOBAL VARIABLES LIKE 'innodb_lock_wait_timeout';+--------------------------+-------+| Variable_name | Value |+--------------------------+-------+| innodb_lock

C# 指定方法的超时时间,超出时限后,直接抛出异常

public static void Invoke(Action method, int milliseconds) { Thread thdToKill = null; Action invokemethod = new Action(() => { thdToKill = Thread.CurrentThread; method(); }); IAsyncResult ar = invokemethod.BeginInvoke(null, null); if (!ar.AsyncWaitHa

Spring事务超时时间可能存在的错误认识

摘自:http://jinnianshilongnian.iteye.com/blog/1986023, 感谢作者. 1.先看代码 1.1.spring-config.xml Java代码   <bean id="dataSource" class="org.springframework.jdbc.datasource.DriverManagerDataSource"> <property name="driverClassName&q

Quartz定时任务和IIS程序池闲置超时时间冲突解决方案

一.问题描述 Bs项目中用Quartz功能执行一个定时任务(每隔5分钟执行一个Job),正常情况,Quartz定时任务会5分钟执行一次,但IIS程序池闲置 超时默认为20分钟,造成的结果是:定时任务只执行了4次.那么怎么解决程序池闲置超时引进Quartz定时任务停止执行问题? 二.解决方案方案一:设置IIS默认闲置超时为1740(跟程序池默认回收时间1740)方案二:IIS服务器规定的时间内,定时向服务器取一次数据 三.方案介绍1)方案一:设置IIS默认闲置超时为1740(跟程序池默认回收时间1

玩转Windows服务系列&mdash;&mdash;Windows服务启动超时时间

最近有客户反映,机房出现断电情况,服务器的系统重新启动后,数据库服务自启动失败.第一次遇到这种情况,为了查看是不是断电情况导致数据库文件损坏,从客户的服务器拿到数据库的日志,进行分析. 数据库工作机制 要分析数据库启动失败的原因,首先说明一下数据库服务的工作机制. 数据库分为六大服务: 数据库的六大服务之间存在依赖关系,及启动流程: 服务自动启动失败原因 从客户那里,拿到了两份日志,一份是开机自启动的日志信息,此次数据库启动失败.另外一份是开机后,手动启动数据库服务的日志信息,此次数据库启动成功

接口调试工具ApiPost的发送超时时间设置方法

有部分使用ApiPost的同学反应:发送接口调试时,响应超时时间设置的太短导致接口访问失败,怎么设置呢? 就连百度也有很多人在搜: 今天就来说一说. ApiPost简介: ApiPost是一个支持团队协作,并可直接生成文档的API调试.管理工具.它支持模拟POST.GET.PUT等常见请求,是后台接口开发者或前端.接口测试人员不可多得的工具 . 官网:https://www.apipost.cn/ ApiPost的发送超时时间设置方法 对于老版本的ApiPost,这个超时时间的确是无法设置的.新

C# 给某个方法设定执行超时时间 C#函数运行超时则终止执行(任意参数类型及参数个数通用版)

在某些情况下(例如通过网络访问数据),常常不希望程序卡住而占用太多时间以至于造成界面假死. 在这时.我们可以通过Thread.Thread + Invoke(UI)或者是 delegate.BeginInvoke 来避免界面假死, 但是这样做时,某些代码或者是某个方法的执行超时的时间还是无法操控的.那么我们又是否有一种比较通用的方法.来设定某一个方法的执行超时的时间,让该其一旦超过指定时间则跳出指定方法.进而继续向下执行呢? 答案当然是肯定的. delegate.BeginInvoke可以实现代

VC socket Connect 超时时间设置

设置connect超时很简单,CSDN上也有人提到过使用select,但却没有一个令人满意与完整的答案.偶所讲的也正是select函数,此函数集成在winsock1.1中,简单点讲,"作用使那些想避免在套接字调用过程中被锁定的应用程序,采取一种有序的方式,同时对多个套接字进行管理"(<Windows网络编程技术>原话).使用方法与解释请见<Windows网络编程技术>. 在使用此函数前,需先将socket设置为非阻塞模式,这样,在connect时,才会立马跳过,