2

Hi guys I start threads with such code:

    Thread[] thr;
    private void button1_Click(object sender, EventArgs e)
    {
        decimal value = numericUpDown2.Value;
        int i = 0;
        threads_count = (int)(value);
        thr = new Thread[threads_count];
        for (; i < threads_count; i++)
        {
            thr[i] = new Thread(new ThreadStart(go));
            thr[i].IsBackground = true;
            thr[i].Start();
        }
    }

How to stop all them if my condition become true

Sergey Berezovskiy
  • 232,247
  • 41
  • 429
  • 459

6 Answers6

22

A number of the answers say to abort the thread. Never abort a thread unless it is an emergency situation and you are shutting down the application.

The CLR guarantees that its internal data structures are not corrupted by a thread abort. This is the only (*) guarantee made by the CLR with respect to thread aborts. It specifically does not guarantee:

  • That the thread actually will abort. Threads can harden themselves against being terminated.
  • That any data structure that is not in the CLR itself will be uncorrupted. Thread aborts in the middle of crucial operations can leave BCL data structures or user data structures in arbitrarily inconsistent states. This can crash your process mysteriously later.
  • That locks will be released. Aborting threads can cause locks to be held forever, it can cause deadlocks, and so on.

In case I am not being clear: it is insanely dangerous to abort a thread and you should only do so when all the alternatives are worse.

So what if you want to start up a thread and then shut it down cleanly?

First, don't do that. Don't start a thread in the first place. Start a Task<T> with a cancellation token and when you want to shut it down, signal its cancellation token.

If you do have to start a thread, then start the thread such that there is some mechanism whereby the main thread and the working thread can cleanly and safely communicate "I want you to shut yourself down cleanly at this time".

If you don't know how to do that then stop writing multithreaded code until you learn how to do that.


(*) This is a small lie; the CLR also makes certain guarantees with respect to the interactions of thread aborts and special code regions such as constrained execution regions and finally blocks.

Eric Lippert
  • 647,829
  • 179
  • 1,238
  • 2,067
2

Brutal way (not recommended) - use Thread.Abort method to abort threads. This method raises ThreadAbortException on thread. Like this:

foreach(Thread thread in thr)
    thread.Abort();

But better way is notifying thread about cancellation and letting it correctly finish its job. You can do it simply with .Net 4 tasks:

Task[] thr = new Task[threads_count];
var source = new CancellationTokenSource();

for (int i = 0; i < threads_count; i++)
{
    thr[i] = Task.Factory.StartNew(go, source.Token);
}

// later, when condition is met
source.Cancel();

And here is how cancellation should look like:

private static void go(object obj)
{
    CancellationToken token = (CancellationToken)obj;
    while (true)
    {
        if (token.IsCancellationRequested)
            return;

        // do some work
    }
}
Sergey Berezovskiy
  • 232,247
  • 41
  • 429
  • 459
  • 3
    +1 as it is the only way to forcefully stop the thread... Also it would be much safer to make threads cooperate in termination. You really don't want to learn all possible side effects of Thread.Abort and way to mitigate them. – Alexei Levenkov Feb 11 '13 at 17:32
  • 3
    I would avoid using `Thread.Abort` to signal a thread to stop. When something like a `CancellationToken` or a Boolean flag can be watched by the thread to stop in a safe manner. But since the thread is in the background that may not be of concern. – JG in SD Feb 11 '13 at 17:33
  • 1
    Agree, that Aborting thread is a brutal solution, but its simplest one. Here is question on this topic http://stackoverflow.com/questions/710070/timeout-pattern-how-bad-is-thread-abort-really/710094#710094 – Sergey Berezovskiy Feb 11 '13 at 17:34
2

You can use a CancellationToken to signal when the operation should stop.

  1. Create a CancellationTokenSource as an instance field of your type that you initialize in the button click handler.

  2. In your background method periodically check the IsCancellationRequested property of the Token in the token source, or call ThrowIfCancellationRequested() if you want it to just throw an exception if it is canceled.

  3. When you want to stop the threads call Cancel on the token source.

Servy
  • 202,030
  • 26
  • 332
  • 449
1

If you want to know how to terminate the thread gracefully, I'd recommend you to take a look the following example on MSDN:

using System;
using System.Threading;

public class Worker
{
    public void DoWork()
    {
        while (!_shouldStop)
        {
            Console.WriteLine("worker thread: working...");
        }
        Console.WriteLine("worker thread: terminating gracefully.");
    }
    public void RequestStop()
    {
        _shouldStop = true;
    }
    // Volatile is used as hint to the compiler that this data
    // member will be accessed by multiple threads.
    private volatile bool _shouldStop;
}

public class WorkerThreadExample
{
    static void Main()
    {
        Worker workerObject = new Worker();
        Thread workerThread = new Thread(workerObject.DoWork);
        workerThread.Start();
        Console.WriteLine("main thread: Starting worker thread...");

        while (!workerThread.IsAlive); // Loop until worker thread activates

        // Put the main thread to sleep for 1 millisecond to
        // allow the worker thread to do some work:
        Thread.Sleep(1);

        workerObject.RequestStop();

        // Use the Join method to block the current thread 
        // until the object's thread terminates.
        workerThread.Join();
        Console.WriteLine("main thread: Worker thread has terminated.");
    }
}
A. Rodas
  • 20,171
  • 8
  • 62
  • 72
  • 2
    Whilst this may theoretically answer the question, [it would be preferable](http://meta.stackexchange.com/q/8259) to include the essential parts of the answer here, and provide the link for reference. – Spontifixus Feb 11 '13 at 17:32
  • Sorry, I'm fairly new here. Thanks for the aclaration! – A. Rodas Feb 11 '13 at 17:37
0

This is Windows Form Code in which:

  • 1) On Clicking start button, Main Thread creates another Thread
  • 2) Again created Thread creates on more Thread.
  • 3) On clicking Stop button, First the last Thread should terminate Then the Thread created by Main thread should Terminate.

    namespace Thread_TerminateProblem
    {    
        public partial class Form1 : Form
        {     
    
    
        private static AutoResetEvent m_ResetEvent = null;                
        private static ManualResetEvent m_ResetEvent_Thread = new ManualResetEvent(false);
        enum ServiceState { Start, Stop };
        bool flag = false;
        int x = 0;
        ServiceState _state;
        public Form1()
        {
            InitializeComponent();
        }
    
        private void btnStart_Click(object sender, EventArgs e)
        {
            flag = true;
            _state = ServiceState.Start;
            m_ResetEvent = new AutoResetEvent(true);            
            Thread t1 = new Thread(fun_Thread1);
            t1.Start();
            t1.Name = "Thread1";            
        }
    
        private void btnStop_Click(object sender, EventArgs e)
        {
            _state = ServiceState.Stop;
            m_ResetEvent.Set();           
        }
    
    
        private void fun_Thread1()
        {
            while (true)
            {                               
                m_ResetEvent.WaitOne();                
                switch (_state)
                {
                    case ServiceState.Start:
                        {                            
                            Thread t = new Thread(fun_Thread2);
                            t.Start();
                            t.Name = "Thread2";
                            break;
                        }
                    case ServiceState.Stop:
                        {
                            m_ResetEvent_Thread.Set();
                            flag = true;
                            break;
                        }
                }
                // When the child Thread terminates, Then only this thread should terminate
                if (flag == true)
                {
                    // Waiting for notification from child Thread
                    notifyParent.WaitOne();
                    Thread.Sleep(100);
                    break;
                }                
                m_ResetEvent.Reset();                              
            }            
        }
    
        private static ManualResetEvent notifyParent = new ManualResetEvent(false);
    
        private void fun_Thread2()
        {
            while (true)
            {
                if (m_ResetEvent_Thread.WaitOne(1, false))
                {
                    notifyParent.Set();
                    break;
                }
                x++;                
            }
        }     
    }
    

    }

-5

simplistic answer is to use the thread Abort() method however your code does not really make it clear what condition,

what loop tests vs a condition? why do you need to abort a thread? I am asking as there may be a better way to approach this

Pharabus
  • 6,081
  • 1
  • 26
  • 39