Реализую периодическое выполнение некоторых операций в фоне.
Задача: последовательное выполнение периодических задач, иметь возможность остановить выполнение, дождаться окончания выполнения фоновых операций.
Грубо: набор функций Start, Stop, Wait.
Я реализовал следующим образом (см код ниже). Покритикуйте пожалуйста (смущает черезчур сложный код с одновременным использованием как блокировки, флага, так и события. Можно ли упростить его?
using System.Threading;
using Timer = System.Timers.Timer;
public class Program
{
private readonly object locker = new object();
// признак простаиванияprivate readonly ManualResetEvent evIdle = new ManualResetEvent(true);
// не используем AutoReset, чтобы избежать араллельных вызовов в случае если длительность Work > Intervalprivate readonly Timer timer = new Timer { Interval = 1, AutoReset = false };
// флаг остановкиprivate bool stop;
public Program()
{
timer.Elapsed += Work;
}
void Work(object sender, System.Timers.ElapsedEventArgs e)
{
lock (locker)
{
// проверка если вызов был уже произведен ("запланирован") когда устанавливали флаг/останавливали таймерif (stop)
return;
evIdle.Reset();
}
// имитация длительной операции
Thread.Sleep(3000);
lock (locker)
{
if (!stop)
timer.Start();
evIdle.Set();
}
}
public void Start()
{
Stop();
Wait();
stop = false;
timer.Start();
}
public void Stop()
{
lock (locker)
{
stop = true;
timer.Stop();
}
}
public void Wait()
{
evIdle.WaitOne();
}
static void Main()
{
var program = new Program();
program.Start();
// пауза - дадим таймеру сработать
Thread.Sleep(10);
program.Stop();
program.Wait();
}
}
Здравствуйте, AK107, Вы писали:
AK>Здравствуйте.
AK>Все молчат, наверное код идеален...
AK>Ну а если серьезно, то все еще жду конструктивных замечаний.
Здравствуйте, achmed, Вы писали:
A>Попробуй проверить c CHESS
потестил: вместо таймера стартовал поток из которого вызывался Work, из другого же поток звал stop и wait.
говорит все гуд.
подтвердил лишь для себя следующие моменты:
void Work(object sender, System.Timers.ElapsedEventArgs e)
{
lock (locker)
{
// проверка если вызов был уже произведен ("запланирован") когда устанавливали флаг/останавливали таймерif (stop)
return;
evIdle.Reset(); // <-- 1*
}
// имитация длительной операции
Thread.Sleep(3000);
lock (locker)
{
if (!stop)
timer.Start();
evIdle.Set(); // 1-- 2*
}
}
1* — evIdle.Reset нельзя выносить за lock, тк Stop и Wait могут быть вызваны между блоком lock и evIdle.Reset.
2* — evIdle.Set можно выносить за lock и ставить его как до так и после рестарта таймера, тк они не связаны в атомарную операцию.
з.ы. то, что работает без ошибок я в принципе знал (скромно так ), я больше хочу услышать критику и возможные шаги по упрощению кода.
Здравствуйте, AK107, Вы писали:
AK>з.ы. то, что работает без ошибок я в принципе знал (скромно так ), я больше хочу услышать критику и возможные шаги по упрощению кода.
А задача конечная есть или это просто придуманные условия?
Здравствуйте, achmed, Вы писали:
A>А задача конечная есть или это просто придуманные условия?
конечно. все реально.
нужно с некоторой периодичностью выполнять некую операцию (выбрал таймер, отдельный поток не хочу). нужно уметь корректино остановить такую периодическую обработку, и, если нужно дождаться окончания обработки (если такова была уже запущена на момент остановки). методы остановки и ожидания иметь отдельно, тк есть другие фоновые потоки обработчики — хочу всем дать команду "остановится" и по очереди дождатья завершения.
з.ы. как по мне, так часто встречающаяся задача неужели никто не сталкивался? или никого не заботит как оно там корректно отработает?
Здравствуйте, AK107, Вы писали:
AK>конечно. все реально.
AK>нужно с некоторой периодичностью выполнять некую операцию (выбрал таймер, отдельный поток не хочу). нужно уметь корректино остановить такую периодическую обработку, и, если нужно дождаться окончания обработки (если такова была уже запущена на момент остановки). методы остановки и ожидания иметь отдельно, тк есть другие фоновые потоки обработчики — хочу всем дать команду "остановится" и по очереди дождатья завершения.
А что делают обработчики, кто или что ими управляет?
AK>з.ы. как по мне, так часто встречающаяся задача неужели никто не сталкивался? или никого не заботит как оно там корректно отработает?
Именно таких задач мне не встречалось .
А по коду — вроде нормально написан .
Здравствуйте, achmed, Вы писали:
A>А что делают обработчики, кто или что ими управляет?
если я правильно понял вопрос, то обработка — это например вызов некоторых вебсервисов в фоне и сбор данных... управления как такого нет: при старте программы запускается таймер, при завршении хочу корректно останавливать периодическую обработку
A>Именно таких задач мне не встречалось .
ну а например, чекать почту раз в минуту, очередь задач (внешнюю, в БД например)?..
A>А по коду — вроде нормально написан .
пасип.
смущает, что как то там много всего одновременно используется для сигнализации