Я провел некоторое исследование и осмотрелся, и, похоже, способ сделать это - использовать AutoResetEvent. Я быстро собрал это вместе, и, похоже, он работает и кажется поточно-ориентированным. Могу я оставить отзыв?
class Program
{
private Thread workerThread;
private AutoResetEvent aResetEvent;
private bool _continueProcessing;
private bool active;
private Object locker = new Object();
public Program()
{
workerThread = new Thread(DoSomeProcessing);
workerThread.IsBackground = true;
aResetEvent = new AutoResetEvent(false);
}
public bool ContinueProcessing
{
get
{
lock (locker)
{
return _continueProcessing;
}
}
set
{
if (value)
{
aResetEvent.Set();
}
else
{
aResetEvent.Reset();
}
lock (locker)
{
_continueProcessing = value;
}
}
}
public void DoSomeProcessing()
{
int i = 0;
try
{
while (active)
{
aResetEvent.WaitOne();
// do some work and sleep
lock (locker)
{
if (ContinueProcessing)
{
aResetEvent.Set();
}
}
}
}
catch(ThreadInterruptedException tie)
{
Console.WriteLine("Shutting down.");
}
// any shutdown processing
}
public void StopProcessing()
{
workerThread.Interrupt();
workerThread.Join();
}
public void PauseProcessing()
{
ContinueProcessing = false;
}
public void Continue()
{
ContinueProcessing = true;
}
public void StartProcessing()
{
ContinueProcessing = true;
active = true;
}
}
РЕДАКТИРОВАТЬ: Привет снова. Я воспользовался отзывами и гораздо больше доволен своей реализацией. Я хотел бы добавить одну небольшую вещь: когда я делаю паузу, я хотел бы подождать, чтобы убедиться, что поток приостановлен и больше не выполняет работу. Это возможно? Может быть, мне просто заменить паузу и возобновить только start и stop, а затем на остановке выполнить thred.join (). Комментарии?
3 ответа
После вызова exit событие ManualResetEvent будет удалено, и при вызове методов экземпляра могут возникать исключения. -> в некоторых случаях это может быть нежелательно
class Program {
static void Main(string[] args) {
//NOTE: if worker goes out of scope it will be collected -> ex: promote to field in real use
Worker worker = new Worker();
System.Threading.Thread workerThread = new System.Threading.Thread(new System.Threading.ThreadStart(worker.DoWork));
workerThread.IsBackground = true;
workerThread.Start();
// test
worker.Resume();
System.Threading.Thread.Sleep(2000);
worker.Pause();
System.Threading.Thread.Sleep(2000);
worker.Resume();
System.Threading.Thread.Sleep(2000);
worker.Exit();
System.Threading.Thread.Sleep(5000);
}
}
public class Worker {
private readonly System.Threading.ManualResetEvent _Gate;
private bool _IsActive;
public Worker() {
_Gate = new System.Threading.ManualResetEvent(false);
_IsActive = true;
}
public void DoWork() {
while (IsActive) {
_Gate.WaitOne();
// do work
// can yield the thread
System.Threading.Thread.Sleep(1);
}
// dispose
_Gate.Close();
}
private bool IsActive {
get {
lock (_Gate) {
return _IsActive;
}
}
}
public void Pause() {
_Gate.Reset();
}
public void Resume() {
_Gate.Set();
}
public void Exit() {
lock (_Gate) {
_IsActive = false;
}
}
}
Выглядит слишком сложным
А также
public void StopProcessing()
{
workerThread.Interrupt();
workerThread.Join();
}
Можно удалить, если вы просто позволите потоку выйти из метода
Если вы перешли на использование ManualResetEvent, вы можете удалить переменную _continueProcessing. В наборе просто вызовите Set или Reset по событию. В получателе вы можете вернуть aResetEvent.WaitOne (0). Затем вы можете удалить фрагмент кода в конце DoSomeProcessing, который устанавливает событие, если обработка должна продолжаться. Кроме того, поскольку ManualResetEvent сам по себе потокобезопасен, вы можете полностью снять блокировку.
Что касается выхода из вашего метода DoSomeProcessing. Вероятно, лучше всего использовать флаг, который вы установили, чтобы сообщить циклу о выходе, проверить флаг от блокировки в начале цикла (да, теперь вам нужно вернуть некоторую блокировку) и когда вы хотите для отмены вы устанавливаете флаг, а затем устанавливаете событие.
В качестве альтернативы вы можете использовать другое событие, чтобы сигнализировать о том, что цикл должен выйти, и изменить время ожидания, чтобы использовать WaitHandle.WaitAny ().
Похожие вопросы
Новые вопросы
.net
НЕ используйте для вопросов о .NET Core - используйте вместо этого [.net-core]. .NET Framework - это программная среда, предназначенная главным образом для операционной системы Microsoft Windows. Он включает в себя реализацию библиотеки базовых классов, общеязыковой среды выполнения (обычно называемой CLR), общей системы типов (обычно называемой CTS) и динамической среды исполнения. Он поддерживает множество языков программирования, включая C #, VB.NET, F # и C ++ / CLI.