我怎样才能暂停/恢复线程? 有一次,我Join()
线程,我不能重新启动它。 那么,如何可以启动一个线程,并使其暂停每当按钮“暂停”被按下,并恢复它,当按下恢复按钮?
这个线程做的唯一的事情,是显示一个标签控件一些随机的文本。
我怎样才能暂停/恢复线程? 有一次,我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
}
}
我建议你阅读在C#线程,由乔阿尔巴哈利 ,特别是暂停和恢复部分:
一个线程可以明确地暂停,并通过过时方法Thread.Suspend和Thread.resume恢复。 这种机制是完全分开的,以阻断的。 这两个系统是独立的并且并行操作。
一个线程可以挂起自己或者另一个线程。 调用暂停的线程简要进入SuspendRequested状态,随后在到达一个点的安全进行垃圾回收的结果,它进入暂停状态。 从那里,它只能通过调用其恢复方法的另一个线程恢复。 简历将在挂起的线程,而不是阻塞的线程才能正常工作。
从.NET 2.0,挂起和恢复已弃用,其使用气馁,因为在任意暂停另一个线程所固有的危险。 如果保持在临界资源锁的线程被挂起,整个应用程序(或计算机)可以死锁。 这远远比调用中止更危险 - 其导致任何这样的锁被释放(至少在理论上)凭借代码在最后块。
这不是手动挂起和恢复线程最好的主意。 然而,你可以很容易地通过使用线程同步原语(如模拟这种行为的ManualResetEvent )
看看这个问题 ,你可能会发现它有用。
但我相信你可以很容易地实现自己的“显示在标签控件随机文本”通过使用计时器以时间为基础的目标。
下面是使用一个简单的例子DispatcherTimer
var timer = new DispatcherTimer();
timer.Tick += (s, e) => Label.Text = GetRandomText();
timer.Interval = TimeSpan.FromMilliseconds(500);
timer.Start();
你可以通过调用暂停timer.Stop()
然后timer.Start()
再次恢复。
下面是对我工作的两种方式。 这两个假定工作线程都有它自己的处理循环。
下面的控制台应用程序的示例显示了这两种方法,使用回调暂停/继续,一个工人方法停止。 回调方法的另一个优点是,它也方便传回的状态更新,而它的检查是否允许继续。
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;
}
}
}