Proper Approach for Temporarily Suspending a Worker Thread

只愿长相守 提交于 2019-12-11 06:51:51

问题


I have a worker thread that may be active for short bursts of time and idle for rest of the time. I'm thinking to put the thread to sleep and then awake it when needed.

Any additional recommendations for this I should be aware of?

Thanks!

  • this is in C#/.NET4

回答1:


Just use an event to pause the worker thread: reset - paused, set - unpaused (working) state.

Here is the draft version of code that demonstrates the approach.

class Worker
{
    private Thread _thread;

    // Un-paused by default.
    private ManualResetEvent _notToBePaused = new ManualResetEvent(true);

    public Worker()
    {
        _thread = new Thread(Run)
            {
                IsBackground = true
            };
    }

    /// <summary>
    /// Thread function.
    /// </summary>
    private void Run()
    {
        while (true)
        {
            // Would block if paused!
            _notToBePaused.WaitOne();

            // Process some stuff here.
        }
    }

    public void Start()
    {
        _thread.Start();
    }

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

    public void UnPause()
    {
        _notToBePaused.Set();
    }
}



回答2:


You should probably not be using a persistent worker thread- use the thread pool. This is exactly what it is intended for.

ThreadPool.QueueUserWorkItem(() => {
    // My temporary work here
});

If you insist on having a persistent worker thread, make it run this:

// This is our latch- we can use this to "let the thread out of the gate"
AutoResetEvent threadLatch = new AutoResetEvent(false);

// The thread runs this
public void DoBackgroundWork() {
    // Making sure that the thread is a background thread
    // ensures that the endless loop below doesn't prevent
    // the program from exiting
    Thread.IsBackground = true;
    while (true) {

        // The worker thread will get here and then block 
        // until someone Set()s the latch:
        threadLatch.WaitOne();

        // Do your work here
    }
}

//  To signal the thread to start:
threadLatch.Set();

Also note that if this background thread is going to interact with the user interface at all, you'll need to Invoke or BeginInvoke accordingly. See http://weblogs.asp.net/justin_rogers/pages/126345.aspx




回答3:


Signaling with WaitHandle is the right way to go, but just to add on what others said already

I'd usually go with 2 signals working together, otherwise you wouldn't know whether to 'continue' or 'exit' when needed - or would have to resort to a less graceful way of doing that (stopping the thread - of course there are other ways of doing something like this, just one 'pattern'). So usually it works with an 'exit' signal and a 'new work available' signal - working in unison. e.g.

WaitHandle[] eventArray = new WaitHandle[2] { _exitEvent, _newWorkEvent };
while ((waitid = WaitHandle.WaitAny(eventArray, timeout, false)) > 1)
{
    // do your work, and optionally handle timeout etc.
}

note:
exit is ManualResetEvent with 'false' initial state - 'Set' event to exit.
_newWork is either Manual in which case you need to pause/continue from outside which is what you wanted I think -
...or could also be new AutoResetEvent(false) which you 'signal' to do one loop of work, signal returns to 'false' right away - and you need to repeat that for each 'new batch' of work - this is a bit simplified. (often that goes hand in hand with some 'messages' being passed along, synchronized of course in some way).

Hope this adds some more info,



来源:https://stackoverflow.com/questions/10047571/proper-approach-for-temporarily-suspending-a-worker-thread

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!