在工作中,遇到这样一个需求,我要做一个业务,要验证一下现有的数据是否正确,但这个验证又不是必须的,只是说如果这里验证不通过,后面流程就可以不走了,但是如果这里没有验证到,后面也会有验证。也就是说不影响主流程,算得上是一个优化吧。比如我要查询一个东西,但是这个时间不能超过1秒。
在网上查了一下,基本上都是异步执行,有两个线程来做。我查到有两种方法。
第一种 独立成一个类
代码如下:
(1)、FuncTimeOut类
///
///超时设置类///
public classFuncTimeOut
{///
///信号量///
private ManualResetEvent manu = new ManualResetEvent(false);///
///是否接受到信号///
private boolisgetSignal;///
///设置超时时间///
private inttimeout;///
///要委托调用的方法的一个委托///
private ActionfuncNeedRun;///
///构造函数///
/// 委托
/// 超时时间
public FuncTimeOut(Action action, inttimeout)
{this.funcNeedRun =action;this.timeout =timeout;
}///
///执行方法///
/// 参数
public void Execute(intparam)
{
Action 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);
}
}///
///回调函数///
/// 异步操作时的状态
private voidMyAsynCallback(IAsyncResult ar)
{if (this.isgetSignal == false)
{
Console.WriteLine(Thread.CurrentThread.Name+ ",超时,放弃执行回调函数");
Thread.CurrentThread.Abort();
}else{
Console.WriteLine(Thread.CurrentThread.Name+ ",执行成功");
}
}///
///执行方法///
/// 参数
private void CombineActionAndManuset(intpara)
{
Thread.CurrentThread.Name= "subThread";this.funcNeedRun(para);this.manu.Set();
}
}
(2)、测试代码
///
///Class Program///
public classProgram
{///
///Defines the entry point of the application.///
/// The args.
public static void Main(string[] args)
{
TestFuncTimeOut();
Console.Read();
}#region FunTimeOut测试
///
///测试超时设置操作///
private static voidTestFuncTimeOut()
{
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");
}///
///Does the STH.///
/// The num.
private static void ComputeSum(intnum)
{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 start2 0:ThreadName:subThread3 1:ThreadName:subThread4 2:ThreadName:subThread5 3:ThreadName:subThread6 4:ThreadName:subThread7 超时8 ThreadName:Main9 ThreadName:Main10 end11 5:ThreadName:subThread12 6:ThreadName:subThread13 7:ThreadName:subThread14 8:ThreadName:subThread15 9:ThreadName:subThread16 sum = 4517 subThread,超时,放弃执行回调函数
b、未超时的情况(将上述黄色部分的标示改为:ft.Execute(3);的结果)
1 start2 0:ThreadName:subThread3 1:ThreadName:subThread4 2:ThreadName:subThread5 sum = 36 未超时.7 ThreadName:Main8 ThreadName:Main9 end10 subThread,执行成功
(4)、总结
从上面的结果可以看出:
第一、有两个线程
第二、无论是否超时,方法都会被执行完毕,如果超时,则不忘下执行回调函数,否则执行。
第二种 封装成一个方法
(1)、源代码
///
///连续整数求和【测试方法】///
/// 个数
/// 结果
private static int ComputeSumResult(intnum)
{int sum = 0;for (int i = 0; i < num; i++)
{
Thread.Sleep(500);
sum+=i;
Console.WriteLine(i+ ",ThreadName:" +Thread.CurrentThread.Name);
}returnsum;
}///
///超时方法调用///
/// 要调用的方法
/// 要调用方法的参数
/// 超时时间
/// 结束
private static int CallWithTimeOutFun(Func func, int param, inttimeoutMillisecondes)
{
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);returnsum;
}else{
Console.WriteLine("ThreadName:" +Thread.CurrentThread.Name);
threadToKill.Abort();
Console.WriteLine("超时");
Console.WriteLine("ThreadName:" +Thread.CurrentThread.Name);returnsum;
}
}
(2)、测试代码
///
///Class Program///
public classProgram
{///
///Defines the entry point of the application.///
/// The args.
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 start2 0,ThreadName:threadToKill3 1,ThreadName:threadToKill4 2,ThreadName:threadToKill5 3,ThreadName:threadToKill6 4,ThreadName:threadToKill7 ThreadName:Main8 超时9 ThreadName:Main10 ThreadName:Main, 结果是:0
11 end
b、不超时的情况(将上面测试需要修改的代码修改为:int result = CallWithTimeOutFun(ComputeSumResult, 3, 3000);// 测试需要修改的代码)
1 start2 0,ThreadName:threadToKill3 1,ThreadName:threadToKill4 2,ThreadName:threadToKill5 ThreadName:Main6 没有超时7 ThreadName:Main8 ThreadName:Main, 结果是:3
9 end
(4)、总结
从上面的结果可以看出:
第一、有两个线程
第二、如果方法超时,则不会将被调用的方法执行完毕,可以看出,方法是执行了,但由于超时,结果是不对的。如果方法没有超时,结果为正确的。这与上面方法的区别在于,方法超时就不会继续执行了。