将超时设置为一个操作

我有对象obj这是第三方组件,

 // this could take more than 30 seconds int result = obj.PerformInitTransaction(); 

我不知道里面发生了什么。 我所知道的是,如果花费更长时间,那就失败了。

如何设置一个超时机制来执行这个操作,这样如果超过30秒我就抛出MoreThan30SecondsException

您可以在单独的线程中运行该操作,然后在线程连接操作中放置一个超时:

 using System.Threading; class Program { static void DoSomething() { try { // your call here... obj.PerformInitTransaction(); } catch (ThreadAbortException) { // cleanup code, if needed... } } public static void Main(params string[] args) { Thread t = new Thread(DoSomething); t.Start(); if (!t.Join(TimeSpan.FromSeconds(30))) { t.Abort(); throw new Exception("More than 30 secs."); } } } 

更简单的使用Task.Wait(TimeSpan)

 using System.Threading.Tasks; var task = Task.Run(() => obj.PerformInitTransaction()); if (task.Wait(TimeSpan.FromSeconds(30))) return task.Result; else throw new Exception("Timed out"); 

如果你不想阻塞主线程,你可以使用System.Threading.Timer :

 private Thread _thread; void Main(string[] args) { _thread = new ThreadStart(ThreadEntry); _thread.Start(); Timer timer = new Timer(Timeout,null,30000,Timeout.Infinite); } void ThreadEntry() { int result = obj.PerformInitTransaction(); } void TimeOut(object state) { // Abort the thread - see the comments _thread.Abort(); throw new ItTimedOutException(); } 

乔恩Skeet有一个较不强制的方式( closures工作线程的优雅 )停止线程比中止。

但是,由于您不能控制PerformInitTransaction()正在执行的操作,因此在Abort失败并使对象处于无效状态时,您可以做的事情不多。 如上所述,如果您能够清除任何中止PerformInitTransaction中止的PerformInitTransaction ,则可以通过捕获ThreadAbortException来执行此操作,但由于它是第三方调用,这意味着猜测您已将方法留在其中的状态。

PerformInitTransaction应该是提供超时的那个。

您需要小心中止这样的操作,特别是在第三方组件中,您(可能)无法访问要修改的代码。

如果中止操作,那么你将不知道你已经离开了底层类的状态。例如,它可能已经获得一个锁,而你的约会导致该锁不被释放。 即使您在中止操作之后销毁了对象,也可能已经改变了某个全局的状态,因此如果不重新启动,您将无法可靠地创build新实例。

你可以看看调用线程中的方法,并在超时时,中止线程并引发exception。 另外,在这种情况下你必须处理ThreadBortedexception。

在这里使用一个辅助类是一个通用的解决scheme的一个很好的例子。

它使用Action委托来避免前面例子中显示的Thread创build/销毁。

我希望这有帮助。