How to start a thread if a button is pressed and stop it if pressed again?

I am using the following code to do what I ask:

private delegate void CallerDelegate(object e);
CallerDelegate caler = new CallerDelegate(MethodToCall);

when the button is clicked:

if (currBusyThrd != null && currBusyThrd.IsAlive)
   {
    currBusyThrd.Abort();
   }
ThreadPool.SetMaxThreads(1, 1);
//queue the work for thread processing
ThreadPool.QueueUserWorkItem(new WaitCallback(WaitCallbackMethod))

WaitCallbackMethod Method:

void WaitCallbackMethod(object stateInfo)
  {
     // argList : i put some argument in a list to use it in "MethodToCall" ...
     BeginInvoke(caler,argList);
  }

and the method that I call downstream is as follows:

void MethodToCall(object args)
 {
 //Here I get the thread I'm calling to stop it when btn clicked again
 currBusyThrd = Thread.CurrentThread;

 // The rest of the code ...
 }

I feel this is wrong ... How to do it right?

In fact, the call will be executed using TextBox_KeyUp .. so every time the user enters a char, the code will be executed again .. and BackgroundWorker does not work.

+5
source share
4 answers

, ( ). , - . , - , Thread .

, ThreadPool , , . ThreadPool , ThreadPool.

, .

private object m_lock = new object();
private bool m_isRunning = false;
private bool m_isAbortRequested = false;

public void OnButtonClick(object sender, EventArgs e) {
  lock ( m_lock ) {
    if ( m_isRunning ) {
      m_isAbortRequested = true;
    } else {
      m_isAbortRequested = false;
      m_isRunning = true;
      ThreadPool.QueueUserWorkItem(BackgroundMethod);
    }
  }
}

private void BackgroundMethod() {
  try {
    DoRealWork();
  } finally {
    lock (m_lock) {
      m_isRunning = false;
    }
  }
}

private void DoRealWork() {
  ...
  if ( m_isAbortRequested ) {
    return;
  }
}
+9

, . ThreadPool. , Thread. , Abort() ; volatile bool , MethodToCall , true. ThreadPool, , , , , , . ThreadPool .

...

private volatile bool stopThread = false;
private Thread workThread;

private void StartThread()
{
    if(workThread == null)
    {
        stopThread = false;
        workThread = new Thread(new ThreadStart(MethodToCall));

        workThread.Start();
    }
}

private void StopThread()
{
    if(workThread != null)
    {
        stopThread = true;

        workThread.Join(); // This makes the code here pause until the Thread exits.

        workThread = null;
    }
}

MethodToCall stopThread boolean , , . ...

private void MethodToCall()
{
    // do some work here and get to a logical stopping point

    if(stopThread)
    {
        // clean up your work

        return;
    }

    // do some more work and get to another stopping point

    if(stopThread)
    {
        // clean up your work

        return;
    }
}

.

+3

, "" , - , System.Threading.ManualResetEvent, , :

private volatile bool _threadRunning = false;
private ManualResetEvent _signal = new ManualResetEvent(false);
private Thread _thread;
private void OnButtonClick(object sender, EventArgs e)
{
    if (!_threadRunning) {
        // Reset the 'signal' event.
        _signal.Reset();
        // Build your thread parameter here.
        object param = ;
        // Create the thread.
        _thread = new Thread(ExecuteThreadLogicConditionally(param));
        // Make sure the thread shuts down automatically when UI closes
        _thread.IsBackground = true;
        // Start the thread.
        _thread.Start();
        // Prevent another thread from being started.
        _threadRunning = true;
    } else {
        // Signal the thread to stop.
        _signal.Set();
        // DO NOT JOIN THE THREAD HERE!  If the thread takes a while
        // to exit, then your UI will be frozen until it does.  Just
        // set the signal and move on.
    }
}
// If the thread is intended to execute its logic over and over until
// stopped, use this callback.
private void ExecuteThreadLogicUntilStopped(object param)
{
    // Use a while loop to prevent the thread from exiting too early.
    while (!_signal.WaitOne(0)) {
        // Put your thread logic here...
    }
    // Set the flag so anther thread can be started.
    _threadRunning = false;
}
// If the thread logic is to be executed once and then wait to be
// shutdown, use this callback.
private void ExecuteThreadLogicOnce(object param)
{
    // Put your thread logic here...
    //
    // Now wait for signal to stop.
    _signal.WaitOne();
    // Set the flag so another thread can be started.
    _threadRunning = false;
}
// If the thread needs to be stopped at any point along the way, use
// this callback.  The key here is to 'sprinkle' checks of the 'signal'
// to see if the thread should stop prematurely.
private void ExecuteThreadLogicConditionally(object param)
{
    if (_signal.WaitOne(0)) { _threadRunning = false; return; }
    // Execute small chunk of logic here...
    if (_signal.WaitOne(0)) { _threadRunning = false; return; }
    // Execute another small chuck of logic here...
    if (_signal.WaitOne(0)) { _threadRunning = false; return; }
    // Continue this pattern through the method.
}

Please note that this solution does not use ThreadPool at all. This can be done easily. And as a suggestion, I would not have guessed with the SetMaxThreads () function on ThreadPool. Just let ThreadPool do the trick. It was designed to be optimal for the way you use it.

+2
source

Try this code ..

using System;
using System.Linq;
using System.Windows.Forms;
using System.Threading;
using System.Diagnostics;

namespace WindowsFormsApplication1
{
    public partial class Form1 : Form
    {
        Thread workerThread = null;
        ManualResetEvent threadInterrupt = new ManualResetEvent(false);

        public Form1()
        {
            InitializeComponent();
        }

        private void button1_Click(object sender, EventArgs e)
        {
            if (this.workerThread == null)
            {
                this.threadInterrupt.Reset();
                this.workerThread = new Thread(() =>
                {
                    int i = 0;
                    while (!this.threadInterrupt.WaitOne(0))
                    {
                        Debug.Print("put your code in here while worker thread running.. " + i.ToString());
                        Thread.Sleep(100);
                        i++;
                    }
                    this.workerThread = null;
                    // worker thread finished in here..
                });
                this.workerThread.IsBackground = true;
                // start worker thread in here
                this.workerThread.Start();
            }
            else
            {
                // stop worker thread in here
                threadInterrupt.Set();
            }
        }

    }
}
+1
source

All Articles