如何暂停/恢复线程(how to pause/resume a thread)

2019-06-24 04:50发布

我怎样才能暂停/恢复线程? 有一次,我Join()线程,我不能重新启动它。 那么,如何可以启动一个线程,并使其暂停每当按钮“暂停”被按下,并恢复它,当按下恢复按钮?

这个线程做的唯一的事情,是显示一个标签控件一些随机的文本。

Answer 1:

也许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
   }
}


Answer 2:

我建议你阅读在C#线程,由乔阿尔巴哈利 ,特别是暂停和恢复部分:

一个线程可以明确地暂停,并通过过时方法Thread.Suspend和Thread.resume恢复。 这种机制是完全分开的,以阻断的。 这两个系统是独立的并且并行操作。

一个线程可以挂起自己或者另一个线程。 调用暂停的线程简要进入SuspendRequested状态,随后在到达一个点的安全进行垃圾回收的结果,它进入暂停状态。 从那里,它只能通过调用其恢复方法的另一个线程恢复。 简历将在挂起的线程,而不是阻塞的线程才能正常工作。

从.NET 2.0,挂起和恢复已弃用,其使用气馁,因为在任意暂停另一个线程所固有的危险。 如果保持在临界资源锁的线程被挂起,整个应用程序(或计算机)可以死锁。 这远远比调用中止更危险 - 其导致任何这样的锁被释放(至少在理论上)凭借代码在最后块。



Answer 3:

这不是手动挂起和恢复线程最好的主意。 然而,你可以很容易地通过使用线程同步原语(如模拟这种行为的ManualResetEvent )

看看这个问题 ,你可能会发现它有用。

但我相信你可以很容易地实现自己的“显示在标签控件随机文本”通过使用计时器以时间为基础的目标。

下面是使用一个简单的例子DispatcherTimer

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

你可以通过调用暂停timer.Stop()然后timer.Start()再次恢复。



Answer 4:

下面是对我工作的两种方式。 这两个假定工作线程都有它自己的处理循环。

  1. 有线程调用回调请求允许继续下去
  2. 有家长调用方法对线程的类,以表示它

下面的控制台应用程序的示例显示了这两种方法,使用回调暂停/继续,一个工人方法停止。 回调方法的另一个优点是,它也方便传回的状态更新,而它的检查是否允许继续。

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


文章来源: how to pause/resume a thread