Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Set thread lifetime at startup

Is there a way to set a value for how long a thread should (maximally) be alive when you start the thread?

Said in another way, with "pseudocode", is there anything like this:

Thread t = new Thread();
t.start();
t.abort_after_x_seconds(30);

which would make the thread abort if it lived more than 30 seconds.

Edit: I still can't get it to work, what I originally had is:

while(true)
{
    if(...)
    {
        Thread t = new Thread(new ThreadStart(startMethod));
        t.start();
    }
    Thread.sleep(...);
}

the problem is that sometimes the threads will hang (I'm not implementing what the threads do so I don't know exactly why (it's a school project, we're noobs at organizing)), so I want to kill those threads. I tried using Tasks and CancellationTokens as in the examples below, but when the Task hangs it can't check if a cancellation request has occured.

like image 370
user2817012 Avatar asked Nov 11 '13 14:11

user2817012


2 Answers

  1. Most of the time, you shouldn't be using Threads, use Tasks instead. They are more convenient and more efficient.
  2. Aborting something is not safe, you should use cooperative cancellation instead. If you're calling a method that supports cancellation, then just pass it a cancellation token that will be cancelled after 30 seconds.

So your code could look like this (using .Net 4.5):

var cts = new CancellationTokenSource(TimeSpan.FromSeconds(30)));
var task = Task.Run(() => YourMethod(cts.Token), cts.Token);
like image 194
svick Avatar answered Oct 01 '22 15:10

svick


[EDIT: My response was far too slow. But I'll leave this here for the sample code.]

You should use co-operative cancellation for this purpose. The thread itself will need to detect when it should exit, and respond appropriately.

There's a thing called a CancellationToken produced from a CancellationTokenSource that you can use for this purpose.

There's even a CancellationTokenSource constructor which lets you set a timeout.

Here's some sample code to demonstrate its use:

using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.Threading;
using System.Threading.Tasks;

namespace Demo
{
    class Program
    {
        private void run()
        {
            using (var tokenSource = new CancellationTokenSource(TimeSpan.FromSeconds(30)))
            {
                var task = Task.Run(() => exampleOne(tokenSource.Token));
                task.Wait();
            }

            using (var tokenSource = new CancellationTokenSource(TimeSpan.FromSeconds(30)))
            {
                var task = Task.Run(() => exampleTwo(tokenSource.Token));
                task.Wait();
            }

            Console.WriteLine("Done.");
        }

        static void exampleZero()
        {
            Console.WriteLine("Starting exampleZero()");

            try
            {
                Thread.Sleep(10000); // Simulate work.
            }

            catch (OperationCanceledException)
            {
                Console.WriteLine("Operation cancelled.");
            }

            Console.WriteLine("Exiting exampleZero()");
        }

        static void exampleOne(CancellationToken cancellation)
        {
            Console.WriteLine("Starting exampleOne()");

            // Busy loop processing.

            while (!cancellation.IsCancellationRequested)
            {
                // Do some work.
            }

            Console.WriteLine("Exiting exampleOne()");
        }

        static void exampleTwo(CancellationToken cancellation)
        {
            Console.WriteLine("Starting exampleTwo()");

            while (!cancellation.WaitHandle.WaitOne(100)) // Wait 100ms between work.
            {
                // Do some work.
            }

            Console.WriteLine("Exiting exampleTwo()");
        }

        static void Main()
        {
            new Program().run();
        }
    }
}
like image 27
Matthew Watson Avatar answered Oct 01 '22 14:10

Matthew Watson