简体   繁体   中英

C# - Stop a thread after XX seconds

I'm using a thread in C# and I would like it to stop after 40 seconds. In fact, I start it, it runs for 40 seconds and then it shoudl stop. Is it possible to use a timeout or a timer ?

There are two approaches:

1. Encapsulated timeout

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. Hence by doing simple DateTime arithmetic you can encapsulate timeout management within your worker thread.

2. External timeout

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.

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.

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.

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. Alternatively, you can mark the start time with a DateTime and then check periodically by subtracting that from 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. Here are some choices:

  • Cancellation . T1 creates a CancellationTokenSource , s , and passes s.Token as state data to thread T2 . T2 checks periodically for s.Token. IsCancellationRequested .
  • Cancellation using Tasks . This is very similar but instead of using explicit tasks, you use the .NET 4.0 Task Parallel Library
  • Condition Checking . T1 sets a boolean value or some other value that T2 can check against. When the condition is satisfied T2 exits

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. 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.

And finally,

If you have calls to Thread.Sleep in T2 , you can combine one of two techniques below with the techniques above:

  • Interrupt . T1 calls Thread.Interrupt on T2 , perhaps after checking that T2 's ThreadState is ThreadState.WaitSleepJoin .
  • Spin Sleep . Instead of using Thread.Sleep implement a "spin 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). Then exit when true (eg instead of Thread.Sleep(10000) , you do SpinSleep(20, 50) .

you can to something like this by using Join on the thread with a timeout of 40sec. 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.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

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