繁体   English   中英

如何暂停/恢复线程

[英]how to pause/resume a thread

如何暂停/恢复线程? 一旦我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#Threading ,特别是Suspend and Resume部分:

可以通过不赞成使用的方法Thread.Suspend和Thread.Resume显式地挂起和恢复线程。 这种机制与阻塞是完全分开的。 两种系统都是独立的,并且可以并行运行。

一个线程可以挂起自身或另一个线程。 调用Suspend会导致线程短暂进入SuspendRequested状态,然后到达可以安全进行垃圾回收的点时,它将进入Suspended状态。 从那里开始,只能通过另一个调用其Resume方法的线程来恢复它。 恢复仅适用于挂起的线程,而不适用于阻塞的线程。

从.NET 2.0开始,不赞成使用Suspend和Resume,因为任意地挂起另一个线程具有固有的危险,因此不建议使用它们。 如果暂停了关键资源锁的线程,则整个应用程序(或计算机)可能会死锁。 这比调用Abort危险得多,后者会导致通过调用finally块中的代码(至少在理论上)释放任何此类锁。

SuspendRequest状态

手动挂起和恢复线程不是最好的主意。 但是,您可以使用线程同步原语(例如ManualResetEvent )轻松模拟此行为。

看一下这个问题 ,您会发现它很有帮助。

但我相信您可以通过使用计时器轻松地实现“在标签控件中显示随机文本”的目标。

这是使用DispatcherTimer的快速示例

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

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

这是为我工作的两种方法。 两者都假定工作线程具有其自己的处理循环。

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

暂无
暂无

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

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