c# -在XX秒后停止线程
本文关键字:线程 XX | 更新日期: 2023-09-27 18:06:48
我在c#中使用一个线程,我希望它在40秒后停止。事实上,我启动它,它运行40秒,然后它应该停止。
是否可以使用超时或计时器?
有两种方法:
1。封装超时
从网络或串口读取数据的线程可以测量从其启动时间开始经过的时间,并且等待数据的时间不超过剩余时间。网络通信api通常提供为操作指定超时的方法。因此,通过执行简单的DateTime算法,您可以在工作线程中封装超时管理。
2。外部超时
使用另一个线程(或者如果可行的话在主线程中执行)等待工作线程在一定的时间限制内完成,如果没有,则中止它。这样的:
// start the worker thread
...
// give it no more than 5 seconds to execute
if (!workerThread.Join(new TimeSpan(0, 0, 5)))
{
workerThread.Abort();
}
根据阻塞操作的级别、对时度性的容忍(即它必须在接近40秒时停止)以及线程必须如何优雅地退出,有几种选择。
合作、内部
如果线程不需要外部控制或信号,并且阻塞操作通常是短暂的(肯定短于40秒),它可以使用秒表来测量经过的时间,然后优雅地退出。或者,您可以用DateTime
标记开始时间,然后通过从DateTime.Now
中减去它来定期检查。
合作、外部
这是另一个线程在确定第二个退出时间后,向另一个线程发送信号的时候。这意味着其他线程必须通过实际检查条件来配合,这意味着任何阻塞操作(如I/O)都不能长时间阻塞,因此它可以检查。以下是一些选择:
-
取消。T1创建CancellationTokenSource,
s
,并将s.Token
作为状态数据传递给线程T2。T2定期检查s.Token.
IsCancellationRequested
- 使用Tasks取消。这非常相似,但不是使用显式任务,而是使用。net 4.0任务并行库
- 条件检查。T1设置一个布尔值或其他值,T2可以检查该值。当条件满足时T2退出
非合作
当T2无法检查某些条件(即无法合作)时,这是一个可能的选择,可能是因为它执行了一些您无法控制的长阻塞操作,例如调用不提供异步或可取消选项的第三方API。在这种情况下,T1可以优雅地尝试通过执行Thread.Join(
超时 )
来停止T2,然后调用Thread.Abort()
注意:最后一个是要避免的,在框架中已被弃用。
最后,
如果您在T2中调用Thread.Sleep
,您可以将以下两种技术之一与上述技术相结合:
-
打断。T1在T2上调用
Thread.Interrupt
,可能在检查T2的ThreadState是ThreadState.WaitSleepJoin
之后。 -
旋转睡觉。而不是使用
Thread.Sleep
实现"旋转睡眠"。这基本上就像一个常规的睡眠,但是你的睡眠间隔更短N次,并返回一个布尔值,指示较小的睡眠是否被中断(当然它必须捕获这个异常)。然后在true时退出(例如,您执行SpinSleep(20, 50)
而不是Thread.Sleep(10000)
)。
当然可以触发一个计时器,然后在计时器到期时杀死一个线程,但与其自己这样做,不如使用一个实用程序,比如Richter的Power Threading库,它允许你在异步任务上设置超时。
你打算如何停止你的线程?中止一个线程并不是一个好主意(如果这是你打算做的)——例如,更多信息请参阅中止定时器线程。使用Power Threading库之类的东西可以让您更优雅地超时一个线程,如果您选择自己超时,则需要考虑如何优雅地结束一个线程。
您可以通过在线程上使用超时为40秒的Join来实现类似的操作。在此之后,您可以尝试彻底关闭线程(您必须自己提供此方法)或使用Abort -但不建议这样做。