暂时挂起工作线程的正确方法

本文关键字:方法 线程 挂起 工作 | 更新日期: 2023-09-27 18:30:28

我有一个工作线程,它可能在短时间内处于活动状态,其余时间处于空闲状态。我想让线进入睡眠状态,然后在需要时唤醒它。

对此,我应该注意任何其他建议吗?

谢谢!

  • 这是在 C#/中。NET4

暂时挂起工作线程的正确方法

您可能不应该使用持久工作线程 - 使用线程池。 这正是它的本意。

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

如果您坚持使用持久工作线程,请使其运行以下命令:

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

另请注意,如果此后台线程要与用户界面交互,则需要相应地调用或开始调用。 见 http://weblogs.asp.net/justin_rogers/pages/126345.aspx

只需使用一个事件来暂停工作线程:重置 - 暂停,设置 - 未暂停(工作)状态。

下面是演示该方法的代码草稿版本。

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

使用 WaitHandle 发出信号是正确的方法,但只是为了补充其他人已经说过的内容

我通常会使用 2 个信号一起工作,否则您将不知道在需要时是"继续"还是"退出" - 或者不得不采用不太优雅的方式来做到这一点(停止线程 - 当然还有其他方法可以做这样的事情,只有一个"模式")。因此,通常它与"退出"信号和"新工作可用"信号一起工作 - 协同工作。例如

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

注意:
退出ManualResetEvent为"假"初始状态 - "设置"事件退出。
_newWork要么是Manual,在这种情况下,您需要从外部暂停/继续,我认为这是您想要的 -
...或者也可以new AutoResetEvent(false)你"发出信号"做一个工作循环,信号立即返回"假"——你需要为每个"新批次"的工作重复这一点——这有点简化。(通常这与一些"消息"的传递密切相关,当然在某种程度上是同步的)。

希望这能增加更多信息,