繁体   English   中英

C#-XX秒后停止线程

[英]C# - Stop a thread after XX seconds

我在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();
}

当然,可以启动一个计时器,然后在计时器到期时杀死线程,但是您自己做起来比使用Richter的Power Threading库之类的实用程序更好,它可以使您在异步任务上设置超时。

您打算如何停止线程? 中止线程不是一个好主意(如果您打算这样做),例如,有关更多信息,请参阅中止计时器线程 使用诸如Power Threading库之类的工具可以使您更优雅地使线程超时,如果您选择自己这样做,则需要考虑如何优雅地结束线程。

根据阻塞操作的级别,对及时性的容忍度(即必须停止接近40秒)以及线程必须优雅退出的方式,有几种选择。

内部合作

如果该线程不需要外部控制或信号,并且具有通常短暂的阻塞操作(某些时间短于40秒),则可以使用秒表来测量经过的时间,然后正常退出。 另外,您可以用DateTime标记开始时间,然后通过从DateTime.Now减去开始时间来进行定期检查。

合作,外部

这是另一个线程在确定是第二个线程退出的时间之后,将信号发送到另一个线程。 这意味着另一个线程必须通过实际检查条件来配合,这意味着任何阻塞操作(例如I / O)都不能长时间阻塞,因此它可以进行检查。 这里有一些选择:

  • 取消 T1创建CancellationTokenSources ,并将s.Token作为状态数据到线程T2。 T2定期检查s.Token. IsCancellationRequested
  • 使用Tasks 取消 这非常相似,但是使用.NET 4.0 Task Parallel Library而不是使用显式任务
  • 条件检查 T1设置布尔值或T2可以检查的其他值。 当条件满足时, T2退出

非合作

T2无法检查某些条件(即无法合作)时,这是一个可能的选择,可能是因为它执行了一些您无法控制的长时间阻塞操作,例如,调用不提供异步操作的第三方API或可取消的选项。 在这种情况下, T1可以通过执行Thread.Join( timeout )并随后调用Thread.Abort()来优雅地尝试停止T2 。注意:避免这种情况,并且在框架中已弃用了此方法。

最后,

如果在T2中调用了Thread.Sleep ,则可以将以下两种技术之一与上述技术结合使用:

  • 中断 T1可能在检查T2ThreadStateThreadState.WaitSleepJoin之后,在T2上调用Thread.Interrupt
  • 旋转睡眠 而不是使用Thread.Sleep实现“旋转睡眠”。 基本上,这类似于常规睡眠,但是您会以较小的间隔睡眠N次,然后返回一个布尔值,指示较小的睡眠是否被中断(当然,它必须捕获此异常)。 然后在为true时退出(例如,您执行SpinSleep(20, 50) Thread.Sleep(10000)而不是Thread.Sleep(10000) SpinSleep(20, 50)

您可以通过在线程上使用Join(超时40秒)来达到类似目的。 之后,您可以尝试正常关闭线程(您必须自己提供方法)或使用Abort-但这并不建议。

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM