How to terminate a worker thread correctly in c#

后端 未结 4 1667
佛祖请我去吃肉
佛祖请我去吃肉 2021-02-15 23:36

Problem statement

I have a worker thread that basically scans a folder, going into the files within it, and then sleeps for a while. The scanning operat

相关标签:
4条回答
  • 2021-02-16 00:04

    Another alternative is to use events:

    private ManualResetEvent _event = new ManualResetEvent(false);
    
    
    public void Run() 
    {
     while (true)
     {
        DoSomethingThatTakesSeveralSeconds();
        if (_event.WaitOne(timeout))
          break;
     }
    }
    
    public void Stop() 
    {
       _event.Set();
       thread.Join();
    }
    
    0 讨论(0)
  • 2021-02-16 00:14

    I came up with separately scheduling the task:

    using System;
    using System.Threading;
    
    namespace ProjectEuler
    {
        class Program
        {
            //const double cycleIntervalMilliseconds = 10 * 60 * 1000;
            const double cycleIntervalMilliseconds = 5 * 1000;
            static readonly System.Timers.Timer scanTimer =
                new System.Timers.Timer(cycleIntervalMilliseconds);
            static bool scanningEnabled = true;
            static readonly ManualResetEvent scanFinished =
                new ManualResetEvent(true);
    
            static void Main(string[] args)
            {
                scanTimer.Elapsed +=
                    new System.Timers.ElapsedEventHandler(scanTimer_Elapsed);
                scanTimer.Enabled = true;
    
                Console.ReadLine();
                scanningEnabled = false;
                scanFinished.WaitOne();
            }
    
            static void  scanTimer_Elapsed(object sender,
                System.Timers.ElapsedEventArgs e)
            {
                scanFinished.Reset();
                scanTimer.Enabled = false;
    
                if (scanningEnabled)
                {
                    try
                    {
                        Console.WriteLine("Processing");
                        Thread.Sleep(5000);
                        Console.WriteLine("Finished");
                    }
                    finally
                    {
                        scanTimer.Enabled = scanningEnabled;
                        scanFinished.Set();
                    }
                }
            }
        }
    }
    
    0 讨论(0)
  • 2021-02-16 00:25

    I recommend to keep it simple:

    while (m_shouldRun)
    {
        DoSomethingThatTakesSeveralSeconds();
        for (int i = 0; i < 5; i++)  // example: 5 seconds sleep
        {
            if (!m_shouldRun)
                break;
            Thread.Sleep(1000);
        }
    }
    
    public void Stop()
    {
        m_shouldRun = false;
        // maybe thread.Join();
    }
    

    This has the following advantages:

    • It smells like busy waiting, but it's not. $NUMBER_OF_SECONDS checks are done during the waiting phase, which is not comparable to the thousands of checks done in real busy waiting.
    • It's simple, which greatly reduces the risk of error in multi-threaded code. All your Stop method needs to do is to set m_shouldRun to false and (maybe) call Thread.Join (if it is necessary for the thread to finish before Stop is left). No synchronization primitives are needed (except for marking m_shouldRun as volatile).
    0 讨论(0)
  • 2021-02-16 00:28

    The way to stop a thread elegantly is to leave it finish by itself. So inside the worker method you could have a boolean variable which will check whether we want to interrupt. By default it will be set to false and when you set it to true from the main thread it will simply stop the scanning operation by breaking from the processing loop.

    0 讨论(0)
提交回复
热议问题