как приостановить / возобновить stream

Как приостановить / возобновить stream? Как только я Join() к streamу, я не могу его перезапустить. Итак, как я могу начать stream и сделать паузу всякий раз, когда нажата кнопка «пауза», и возобновить ее при нажатии кнопки возобновления?

Единственное, что делает этот stream, – это показать некоторый случайный текст в элементе управления меткой.

Возможно, 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 } } 

Я мог бы предложить вам прочитать Threading in C # Джо Альбахари , в частности раздел Suspend and Resume :

Поток может быть явно приостановлен и возобновлен с помощью устаревших методов Thread.Suspend и Thread.Resume. Этот механизм полностью отделен от механизма блокировки. Обе системы независимы и работают параллельно.

Нить может приостановить себя или другой stream. Вызов Suspend приводит к тому, что stream кратко входит в состояние SuspendRequested, а затем, достигнув точки безопасности для сбора мусора, переходит в состояние Suspended. Оттуда он может быть возобновлен только через другой stream, который вызывает его метод Resume. Возобновление будет работать только на приостановленном streamе, а не на заблокированном streamе.

Из .NET 2.0 Suspend и Resume устарели, их использование не рекомендуется из-за опасности, присущей произвольному приостановке другого streamа. Если stream, удерживающий блокировку на критическом ресурсе, приостанавливается, все приложение (или компьютер) может блокироваться. Это гораздо более опасно, чем вызов Abort – что приводит к тому, что любые такие блокировки освобождаются (по крайней мере теоретически) на основе кода в блоках finally.

SuspendRequested state

Это не лучшая идея, чтобы вручную приостанавливать и возобновлять streamи. Однако вы можете легко имитировать это поведение, используя примитивы синхронизации streamов (например, ManualResetEvent )

Взгляните на этот вопрос , вы можете найти его полезным.

Но я считаю, что вы можете легко достичь своей цели «показывать случайный текст в контроле над меткой» на основе времени, используя таймеры.

Вот краткий пример использования DispatcherTimer

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

Вы можете приостановить его, вызвав timer.Stop() а затем снова возобновить timer.Start() .

Вот два способа, которые сработали для меня. Оба предполагают, что рабочий stream имеет собственный цикл обработки.

  1. Попросите stream вызвать обратный вызов, чтобы запросить разрешение на продолжение
  2. Попросите родителя вызвать метод в classе streamа, чтобы сигнализировать об этом

В приведенном ниже примере приложения консоли показаны оба подхода, используя обратный вызов для приостановки / продолжения и рабочий метод для остановки. Другим преимуществом метода обратного вызова является то, что он также удобен для передачи обновлений статуса, когда он проверяет разрешение на продолжение.

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