简体   繁体   English

如何暂停/恢复线程

[英]how to pause/resume a thread

How can I pause/resume a thread? 如何暂停/恢复线程? Once I Join() a thread, I can't restart it. 一旦我Join()了一个线程,就无法重新启动它。 So how can I start a thread and make it pause whenever the button 'pause' is pressed, and resume it when resume button is pressed? 那么,如何在按下“暂停”按钮时启动线程并使其暂停,并在按下“恢复”按钮时恢复线程?

The only thing this thread does, is show some random text in a label control. 该线程唯一要做的就是在标签控件中显示一些随机文本。

Maybe the ManualResetEvent is a good choice. 也许ManualResetEvent是一个不错的选择。 A short example: 一个简短的例子:

private static EventWaitHandle waitHandle = new ManualResetEvent(initialState: true); 

// Main thread
public void OnPauseClick(...) {
   waitHandle.Reset();
}

public void OnResumeClick(...) {
   waitHandle.Set();
}

// Worker thread
public void DoSth() {
   while (true) {
     // show some random text in a label control (btw. you have to
     // dispatch the action onto the main thread)
     waitHandle.WaitOne(); // waits for the signal to be set
   }
}

I could suggest you to read Threading in C#, by Joe Albahari , particularly Suspend and Resume section: 我建议您阅读Joe Albahari的C#Threading ,特别是Suspend and Resume部分:

A thread can be explicitly suspended and resumed via the deprecated methods Thread.Suspend and Thread.Resume. 可以通过不赞成使用的方法Thread.Suspend和Thread.Resume显式地挂起和恢复线程。 This mechanism is completely separate to that of blocking. 这种机制与阻塞是完全分开的。 Both systems are independent and operate in parallel. 两种系统都是独立的,并且可以并行运行。

A thread can suspend itself or another thread. 一个线程可以挂起自身或另一个线程。 Calling Suspend results in the thread briefly entering the SuspendRequested state, then upon reaching a point safe for garbage collection, it enters the Suspended state. 调用Suspend会导致线程短暂进入SuspendRequested状态,然后到达可以安全进行垃圾回收的点时,它将进入Suspended状态。 From there, it can be resumed only via another thread that calls its Resume method. 从那里开始,只能通过另一个调用其Resume方法的线程来恢复它。 Resume will work only on a suspended thread, not a blocked thread. 恢复仅适用于挂起的线程,而不适用于阻塞的线程。

From .NET 2.0, Suspend and Resume have been deprecated, their use discouraged because of the danger inherent in arbitrarily suspending another thread. 从.NET 2.0开始,不赞成使用Suspend和Resume,因为任意地挂起另一个线程具有固有的危险,因此不建议使用它们。 If a thread holding a lock on a critical resource is suspended, the whole application (or computer) can deadlock. 如果暂停了关键资源锁的线程,则整个应用程序(或计算机)可能会死锁。 This is far more dangerous than calling Abort — which results in any such locks being released (at least theoretically) by virtue of code in finally blocks. 这比调用Abort危险得多,后者会导致通过调用finally块中的代码(至少在理论上)释放任何此类锁。

SuspendRequest状态

It's not the best idea to manually suspend and resume threads. 手动挂起和恢复线程不是最好的主意。 However, you can easily simulate this behavior by using thread synchronization primitives (like ManualResetEvent ) 但是,您可以使用线程同步原语(例如ManualResetEvent )轻松模拟此行为。

Take a look at this question , you may find it helpful. 看一下这个问题 ,您会发现它很有帮助。

But I believe you can easily achieve your goal of 'showing random text in a label control' on a time basis by using timers. 但我相信您可以通过使用计时器轻松地实现“在标签控件中显示随机文本”的目标。

Here is a quick example using DispatcherTimer 这是使用DispatcherTimer的快速示例

var timer = new DispatcherTimer(); 
timer.Tick += (s, e) => Label.Text = GetRandomText(); 
timer.Interval = TimeSpan.FromMilliseconds(500); 
timer.Start();

You can pause it by calling timer.Stop() and then timer.Start() again to resume. 你可以通过调用暂停timer.Stop()然后timer.Start()再次恢复。

Here's two ways that's worked for me. 这是为我工作的两种方法。 Both assume that the worker thread has it's own processing loop. 两者都假定工作线程具有其自己的处理循环。

  1. Have the thread invoke a callback to request permission to keep going 让线程调用回调以请求许可以继续进行
  2. Have the parent invoke a method on the thread's class to signal it 让父级在线程的类上调用一个方法来发出信号

The console application example below shows both approaches, using a callback to pause/continue, and a worker method to stop. 下面的控制台应用程序示例显示了两种方法:使用回调暂停/继续和使用工作方方法停止。 Another advantage of the callback method is that it's also convenient for passing back status updates while it's checking for permission to continue. 回调方法的另一个优点是,在检查继续权限时,还可以方便地回传状态更新。

using System;
using System.Threading;

namespace ConsoleApplication7
{
    class Program
    {
        static bool keepGoing;
        static void Main(string[] args)
        {
            keepGoing = true;
            Worker worker = new Worker(new KeepGoingDelegate(KeepGoing));
            Thread thread = new Thread(worker.DoWork);
            thread.IsBackground = true;
            thread.Start();

            while (thread.ThreadState != ThreadState.Stopped)
            {
                switch (Console.ReadKey(true).KeyChar)
                {
                    case 'p':
                        keepGoing = false;
                        break;
                    case 'w':
                        keepGoing = true;
                        break;
                    case 's':
                        worker.Stop();
                        break;
                }
                Thread.Sleep(100);
            }
            Console.WriteLine("Done");
            Console.ReadKey();
        }

        static bool KeepGoing()
        {
            return keepGoing;
        }
    }

    public delegate bool KeepGoingDelegate();
    public class Worker
    {
        bool stop = false;
        KeepGoingDelegate KeepGoingCallback;
        public Worker(KeepGoingDelegate callbackArg)
        {
            KeepGoingCallback = callbackArg;
        }

        public void DoWork()
        {
            while (!stop)
            {
                Console.Write(KeepGoingCallback()?"\rWorking":"\rPaused ");

                Thread.Sleep(100);
            }
            Console.WriteLine("\nStopped");
        }

        public void Stop()
        {
            stop = true;
        }
    }
}

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM