代码之家  ›  专栏  ›  技术社区  ›  Eldad Mor

如何在c语言中正确终止工作线程#

  •  7
  • Eldad Mor  · 技术社区  · 16 年前

    问题陈述

    我有一个工作线程,它基本上扫描一个文件夹,进入其中的文件,然后休眠一段时间。扫描操作可能需要2-3秒,但不会更多。我在想办法优雅地停止这条线。

    澄清 睡觉 ,而不是在 . 但是,问题是我不知道线程的当前状态是什么。如果它睡着了,我要它立刻离开。如果它正在扫描,我希望它在试图阻止的时候退出。

    尝试解决方案

    一开始我用的是睡眠和打断。然后我发现中断并没有真正中断睡眠-它只在线程试图进入睡眠时起作用。

    while (m_shouldRun)
    {
        try
        {
            DoSomethingThatTakesSeveralSeconds();
            lock (this)
            {
                Monitor.Wait(this, 5000);
            }
        }
        catch (ThreadInterruptedException)
        {
            m_shouldRun = false;
        }
    }
    

    现在我需要设计我的停止函数。所以我从:

    public void Stop()
    {
        m_shouldRun = false;
        lock (this)
        {
            Monitor.Pulse(this);
        }
        thread.Join();
    }
    

    但是这不起作用,因为我可能在线程工作时(在线程不等待时)脉冲。所以我加了一句话:

    public void Stop()
    {
        m_shouldRun = false;
        thread.Interrupt();
        lock (this)
        {
            Monitor.Pulse(this);
        }
        thread.Join();
    }
    

    另一种选择是使用:

    public void Stop()
    {
        m_shouldRun = false;
        while (!thread.Join(1000))
        {
            lock (this)
            {
                Monitor.Pulse(this);
            }
        }
    }
    

    问题

    4 回复  |  直到 16 年前
        1
  •  8
  •   liggett78    16 年前

    private ManualResetEvent _event = new ManualResetEvent(false);
    
    
    public void Run() 
    {
     while (true)
     {
        DoSomethingThatTakesSeveralSeconds();
        if (_event.WaitOne(timeout))
          break;
     }
    }
    
    public void Stop() 
    {
       _event.Set();
       thread.Join();
    }
    
        2
  •  9
  •   Darin Dimitrov    16 年前

    优雅地停止线程的方法是让它自己完成。因此,在worker方法中,可以有一个布尔变量来检查是否需要中断。默认情况下,它将设置为 false true

        3
  •  1
  •   Heinzi    16 年前

    我建议保持简单:

    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();
    }
    

    • 闻起来像是在忙着等,其实不是。$NUMBER秒的检查是在等待阶段完成的,这与在真正繁忙的等待阶段完成的数千次检查不可比。
    • Stop 方法需要做的是设置 m_shouldRun Thread.Join (如果有必要在 住手 左)。不需要同步原语(标记除外) 你该跑了
        4
  •  0
  •   Regent    16 年前

    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();
                    }
                }
            }
        }
    }