如何暂停/恢复一个帖子

时间:2012-05-06 10:06:24

标签: c# wpf multithreading resume

如何暂停/恢复线程?一旦我Join()一个线程,我就无法重启它。 那么,每当按下“暂停”按钮时,如何启动一个线程并使其暂停,并在按下恢复按钮时恢复它?

这个线程唯一能做的就是在标签控件中显示一些随机文本。

4 个答案:

答案 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块中的代码被释放(至少在理论上)。

SuspendRequested state

答案 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)

这有两种方式对我有用。两者都假设工作线程有自己的处理循环。

  1. 让线程调用回调来请求继续使用的权限
  2. 让父级调用线程类的方法来发信号通知
  3. 下面的控制台应用程序示例显示了两种方法,使用回调暂停/继续,以及要停止的工作方法。回调方法的另一个优点是,在检查是否允许继续时,还可以方便地传回状态更新。

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