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