日期:2014-05-17  浏览次数:20658 次

请教通过线程执行一个方法,如何设定执行超时时间?
有一个方法比较耗时,需要后台线程来执行,但又不希望这个方法执行时间过长,希望能设定一个超时时间,当到达超时时间时这个方法还没执行完,就强行终止线程,请问如何实现?

------解决方案--------------------
线程中启动一个timer及时,到了时间,就线程自己退出
------解决方案--------------------
引用:
有一个方法比较耗时,需要后台线程来执行,但又不希望这个方法执行时间过长,希望能设定一个超时时间,当到达超时时间时这个方法还没执行完,就强行终止线程,请问如何实现?


你怎样强行终止线程?

不要说你看到过线程有个“Abort”方法就以为搞定了吧?!
------解决方案--------------------
不要老想着怎么强制取消一个任务或者终止一条线程。ThreadPool也根本不支持这种操作,更别说什么到了一定时间自动取消了。
线程倒是有个Abort()方法,不过功能也是非常有限的,只有当控制权在CLR的时候才能终止线程。也就是只有当线程在执行托管代码的时候才能终止线程,如果代码已经运行到非托管代码中去了,比如你已经进入到处理数据库连接的非托管代码了,Thread.Abort()是无能为力的。

你要的效果当然可以实现,但不是以你想的那种方法。比如数据库连接,首先它自己就支持设置超时时间,你何必要搞一出强制终止线程的戏呢。
其次,就算是为了程序的响应度,连几秒钟都不想阻塞,你也是连线程都用不着创建。Connection对象自带OpenAsync方法用于异步连接,这个方法还可以接收一个CancellationToken,让你可以主动请求取消连接。而CancellationTokenSource又支持在一定时间后自动发出取消请求,你的问题不就迎刃而解了。
            var con = new System.Data.SqlClient.SqlConnection();
            // 2000ms后自动发出取消请求
            CancellationTokenSource cts = new CancellationTokenSource(2000);
            try
            {
                con.OpenAsync(cts.Token);
            }
            catch (Exception)
            {
            }


网路操作也是一样的。有人“喜欢”开一条线程去调用WebClient.DonwLoadString()之类的同步函数,然后发现Thread.Abort()终止不掉,大呼坑爹。其实WebClient本身就提供了异步下载函数和用于取消异步下载的CancelAnsyc()函数。

这些是.NET框架中自带类型的例子。
如果你希望自己定义的某些操作也可以取消,你就要把这个操作设计和实现为可以主动取消。而不是投机取巧考虑用一个线程来执行这个操作,然后要取消的时候就终止线程什么的。


------解决方案--------------------
可以使用信号变量来控制,比如AutoResetEvent的WaitOne方法定义下超时时间。