.Net Thread.Suspend已经过时了。寻找替代方案

时间:2010-02-12 12:22:31

标签: .net multithreading

我做了一些研究并环顾四周,似乎这样做的方法是使用AutoResetEvent。我很快把它放在一起,它似乎工作,似乎是线程安全的。我可以得到一些反馈吗?

class Program
{
    private Thread workerThread;
    private AutoResetEvent aResetEvent;
    private bool _continueProcessing;
    private bool active;
    private Object locker = new Object();

    public Program()
    {
        workerThread = new Thread(DoSomeProcessing);
        workerThread.IsBackground = true;
        aResetEvent = new AutoResetEvent(false);
    }

    public bool ContinueProcessing
    {
        get
        {
            lock (locker)
            {
                return _continueProcessing;
            }
        }
        set 
        {
            if (value)
            {
                aResetEvent.Set();
            }
            else
            {

                aResetEvent.Reset();
            }
            lock (locker)
            {
                _continueProcessing = value;
            }
        }
    }

    public void DoSomeProcessing()
    {
        int i = 0;
        try
        {
            while (active)
            {
                aResetEvent.WaitOne();
                // do some work and sleep
                lock (locker)
                {
                    if (ContinueProcessing)
                    {
                        aResetEvent.Set();
                    }
                }
            }
        }
        catch(ThreadInterruptedException tie)
        {
            Console.WriteLine("Shutting down.");
        }
        // any shutdown processing            
    }

    public void StopProcessing()
    {
        workerThread.Interrupt();
        workerThread.Join();
    }

    public void PauseProcessing()
    {
        ContinueProcessing = false;
    }

    public void Continue()
    {
        ContinueProcessing = true;
    }

    public void StartProcessing()
    {
        ContinueProcessing = true;
        active = true;
    }
}

编辑: 你好,我们又见面了。我已经使用了反馈,我对我的实现更满意。我想添加一个小东西,当我暂停时,我想等待确保线程暂停并且不再工作。那可能吗?也许我应该只用暂停和停止来替换暂停和恢复,然后在停止时执行thred.join()。评论

3 个答案:

答案 0 :(得分:1)

调用exit后,ManualResetEvent将被释放,并且在调用时可能会在实例方法上抛出异常。 - >在某些情况下这可能并不理想

 class Program {
        static void Main(string[] args) {

            //NOTE: if worker goes out of scope it will be collected -> ex: promote to field in real use
            Worker worker = new Worker();
            System.Threading.Thread workerThread = new System.Threading.Thread(new System.Threading.ThreadStart(worker.DoWork));
            workerThread.IsBackground = true;
            workerThread.Start();

            // test 
            worker.Resume();
            System.Threading.Thread.Sleep(2000);

            worker.Pause();
            System.Threading.Thread.Sleep(2000);

            worker.Resume();
            System.Threading.Thread.Sleep(2000);

            worker.Exit();
            System.Threading.Thread.Sleep(5000);        
        }
    }

    public class Worker {

        private readonly System.Threading.ManualResetEvent _Gate;
        private bool _IsActive;

        public Worker() {

            _Gate = new System.Threading.ManualResetEvent(false);
            _IsActive = true;
        }

        public void DoWork() {

            while (IsActive) {
                _Gate.WaitOne();
                // do work

                // can yield the thread 
                System.Threading.Thread.Sleep(1);
            }

            // dispose
            _Gate.Close();
        }

        private bool IsActive {
            get {
                lock (_Gate) {
                    return _IsActive;
                }
            }
        }

        public void Pause() {
            _Gate.Reset();
        }

        public void Resume() {
            _Gate.Set();
        }

        public void Exit() {
            lock (_Gate) {
                _IsActive = false;
            }
        }
    }

答案 1 :(得分:0)

看起来过于复杂

 public void StopProcessing() 
    { 
        workerThread.Interrupt(); 
        workerThread.Join(); 
    } 
如果让线程退出方法

,则可以删除

答案 2 :(得分:0)

如果您更改为使用ManualResetEvent,则可以删除_continueProcessing变量。在集合中只需调用事件上的Set或Reset。在getter中,您可以返回aResetEvent.WaitOne(0)。然后,您可以在DoSomeProcessing结束时删除该段代码,如果处理应该是contine,则设置事件。另外,因为ManualResetEvent本身是线程安全的,你可以完全删除锁定。

关于退出DoSomeProcessing方法。可能最好的办法是使用你设置的标志来告诉循环退出,在循环开始时使用锁定来测试标志(是的,你现在必须放回一些锁定)并且你想要什么时候要中止,你设置标志,然后设置事件。

另外,您可以使用另一个事件来表示循环应该退出并更改您的等待以使用WaitHandle.WaitAny()。