简体   繁体   English

C#-XX秒后停止线程

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

I'm using a thread in C# and I would like it to stop after 40 seconds. 我在C#中使用线程,我希望它在40秒后停止。 In fact, I start it, it runs for 40 seconds and then it shoudl stop. 实际上,我启动了它,运行了40秒,然后它停止了。 Is it possible to use a timeout or a timer ? 是否可以使用超时或计时器?

There are two approaches: 有两种方法:

1. Encapsulated timeout 1.封装超时

The thread reading the data from network or serial port can measure time elapsed from its time of start and wait for the data for no more than the remaining time. 从网络或串行端口读取数据的线程可以测量从其启动时间起经过的时间,并且等待数据的时间不得超过剩余时间。 Network communication APIs usually provide means to specify a timeout for the operation. 网络通信API通常提供指定操作超时的方法。 Hence by doing simple DateTime arithmetic you can encapsulate timeout management within your worker thread. 因此,通过执行简单的DateTime算法,可以将超时管理封装在工作线程中。

2. External timeout 2.外部超时

Use another thread (or do it in the main thread if that's feasible) to wait for the worker thread to finish within a certain time limit, and if not, abort it. 使用另一个线程(或在可行的情况下在主线程中执行此操作)以等待工作线程在特定时限内完成,否则,请中止该线程。 Like this: 像这样:

// start the worker thread
...

// give it no more than 5 seconds to execute
if (!workerThread.Join(new TimeSpan(0, 0, 5)))
{    
    workerThread.Abort();
}

It is certainly possible to kick of a timer and then kill a thread when the timer expires, but rather than do this yourself you might be better of using a utility such as Richter's Power Threading library that allows you to set timeouts on async tasks. 当然,可以启动一个计时器,然后在计时器到期时杀死线程,但是您自己做起来比使用Richter的Power Threading库之类的实用程序更好,它可以使您在异步任务上设置超时。

How are you planning to stop your thread? 您打算如何停止线程? Aborting a thread is not a great idea (if this is what you planned to do) - eg see aborting timer threads for more info. 中止线程不是一个好主意(如果您打算这样做),例如,有关更多信息,请参阅中止计时器线程 Using something like the Power Threading library allows you to more elegantly time out a thread, if you do chose to do it yourself you'll need to consider how a thread can be ended gracefully. 使用诸如Power Threading库之类的工具可以使您更优雅地使线程超时,如果您选择自己这样做,则需要考虑如何优雅地结束线程。

There are several alternatives depending on the level of blocking operations, tolerance for timeliness (ie how close to 40 sec it must stop), and how gracefully the thread must exit. 根据阻塞操作的级别,对及时性的容忍度(即必须停止接近40秒)以及线程必须优雅退出的方式,有几种选择。

Cooperative, Internal 内部合作

If the thread requires no external control or signal and has blocking operations that are generally short lived (certainly shorter than 40 sec), it can use a Stopwatch to measure the elapsed time, and then gracefully quit. 如果该线程不需要外部控制或信号,并且具有通常短暂的阻塞操作(某些时间短于40秒),则可以使用秒表来测量经过的时间,然后正常退出。 Alternatively, you can mark the start time with a DateTime and then check periodically by subtracting that from DateTime.Now . 另外,您可以用DateTime标记开始时间,然后通过从DateTime.Now减去开始时间来进行定期检查。

Cooperative, External 合作,外部

This is when another thread after determining it is time for the second to quit, sends a signal to the other thread. 这是另一个线程在确定是第二个线程退出的时间之后,将信号发送到另一个线程。 This means the other thread has to cooperate by actually checking for the condition, which means any blocking operation such as I/O must not block for long, so it can check. 这意味着另一个线程必须通过实际检查条件来配合,这意味着任何阻塞操作(例如I / O)都不能长时间阻塞,因此它可以进行检查。 Here are some choices: 这里有一些选择:

  • Cancellation . 取消 T1 creates a CancellationTokenSource , s , and passes s.Token as state data to thread T2 . T1创建CancellationTokenSources ,并将s.Token作为状态数据到线程T2。 T2 checks periodically for s.Token. T2定期检查s.Token. IsCancellationRequested . IsCancellationRequested
  • Cancellation using Tasks . 使用Tasks 取消 This is very similar but instead of using explicit tasks, you use the .NET 4.0 Task Parallel Library 这非常相似,但是使用.NET 4.0 Task Parallel Library而不是使用显式任务
  • Condition Checking . 条件检查 T1 sets a boolean value or some other value that T2 can check against. T1设置布尔值或T2可以检查的其他值。 When the condition is satisfied T2 exits 当条件满足时, T2退出

Non-Cooperative 非合作

This is a possible choice when T2 is unable to check for some condition (ie unable to cooperate) likely because it performs some long blocking operation over which you have no control, for example calling a third-party API that doesn't offer an asynchronous or cancellable option. T2无法检查某些条件(即无法合作)时,这是一个可能的选择,可能是因为它执行了一些您无法控制的长时间阻塞操作,例如,调用不提供异步操作的第三方API或可取消的选项。 In this case T1 can gracefully try to stop T2 by doing a Thread.Join( timeout ) , followed by a call to Thread.Abort() Note: This last is to be avoided and has been deprecated in the framework. 在这种情况下, T1可以通过执行Thread.Join( timeout )并随后调用Thread.Abort()来优雅地尝试停止T2 。注意:避免这种情况,并且在框架中已弃用了此方法。

And finally, 最后,

If you have calls to Thread.Sleep in T2 , you can combine one of two techniques below with the techniques above: 如果在T2中调用了Thread.Sleep ,则可以将以下两种技术之一与上述技术结合使用:

  • Interrupt . 中断 T1 calls Thread.Interrupt on T2 , perhaps after checking that T2 's ThreadState is ThreadState.WaitSleepJoin . T1可能在检查T2ThreadStateThreadState.WaitSleepJoin之后,在T2上调用Thread.Interrupt
  • Spin Sleep . 旋转睡眠 Instead of using Thread.Sleep implement a "spin sleep". 而不是使用Thread.Sleep实现“旋转睡眠”。 This is basically like a regular sleep but you sleep for smaller intervals N times, and return a boolean indicating whether the smaller sleep was interrupted (of course it has to catch this exception). 基本上,这类似于常规睡眠,但是您会以较小的间隔睡眠N次,然后返回一个布尔值,指示较小的睡眠是否被中断(当然,它必须捕获此异常)。 Then exit when true (eg instead of Thread.Sleep(10000) , you do SpinSleep(20, 50) . 然后在为true时退出(例如,您执行SpinSleep(20, 50) Thread.Sleep(10000)而不是Thread.Sleep(10000) SpinSleep(20, 50)

you can to something like this by using Join on the thread with a timeout of 40sec. 您可以通过在线程上使用Join(超时40秒)来达到类似目的。 After this you can try to shut the thread cracefully down (you have to provide the means for this yourself) or you use Abort - but this is not advised. 之后,您可以尝试正常关闭线程(您必须自己提供方法)或使用Abort-但这并不建议。

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

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