如何暂停/恢复一个post
如何暂停/恢复线程? 一旦我Join()
一个线程,我就无法重启它。 那么,每当按下按钮“暂停”时,如何启动一个线程并使其暂停,并在按下恢复按钮时恢复它?
这个线程唯一能做的就是在标签控件中显示一些随机文本。
也许ManualResetEvent
是一个不错的选择。 一个简短的例子:
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 } }
我建议你阅读Joe Albahari的C#中的线程 ,特别是Suspend and Resume部分:
可以通过弃用的方法Thread.Suspend和Thread.Resume显式挂起和恢复线程。 这种机制与阻塞机制完全分开。 两个系统都是独立的并且并行运行。
线程可以挂起自己或其他线程。 调用Suspend导致线程暂时进入SuspendRequested状态,然后在达到垃圾收集安全点时,它进入Suspended状态。 从那里,它只能通过另一个调用其Resume方法的线程来恢复。 Resume只能在挂起的线程上工作,而不是阻塞的线程。
从.NET 2.0开始,Suspend和Resume已被弃用,由于任意暂停另一个线程所固有的危险,因此不鼓励使用它们。 如果暂停对关键资源进行锁定的线程,则整个应用程序(或计算机)可能会死锁。 这比调用Abort更危险 – 这导致任何这样的锁通过finally块中的代码被释放(至少在理论上)。
手动挂起和恢复线程并不是最好的主意。 但是,您可以使用线程同步原语(如ManualResetEvent )轻松模拟此行为
看看这个问题 ,你会发现它很有帮助。
但我相信您可以通过使用计时器轻松实现“在标签控件中显示随机文本”的目标。
以下是使用DispatcherTimer的快速示例
var timer = new DispatcherTimer(); timer.Tick += (s, e) => Label.Text = GetRandomText(); timer.Interval = TimeSpan.FromMilliseconds(500); timer.Start();
您可以通过调用timer.Stop()
然后再次使用timer.Stop()
来暂停它。
这有两种方式对我有用。 两者都假设工作线程有自己的处理循环。
- 让线程调用回调来请求继续使用的权限
- 让父进程调用线程类的方法来发信号
下面的控制台应用程序示例显示了两种方法,使用回调暂停/继续,以及要停止的工作方法。 回调方法的另一个优点是,在检查是否允许继续时,还可以方便地传回状态更新。
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; } } }