System.Timer и Pause

 
0
 
.NET
ava
DragonFire | 01.01.2010, 19:45
Задача такая - есть N объектов, у каждого из них есть встроенный таймер. Таймер может сработать в произвольное (заранее не известное) время.
При срабатывании таймера у какого-либо объекта необходимо выполнить длинный ресурсоемкий код. Но если все делать в лоб, пока код выполняется, срабатывают (или могут сработать) другие таймеры и логика программы будет нарушена.
Мне необходимо "ставить на паузу" все остальные таймеры, при срабатывании одного, а после выполнения кода обработчика, возобновлять работу.
Как такое реализовать?
Ответы (9)
ava
Экскалупатор | 01.01.2010, 20:37 #
Создай класс, который в отдельном потоке будет управлять всеми остальными потоками.
ava
Heinzz | 01.01.2010, 21:32 #
я бы сделал иначе. Создайте очередь в которую будут попадать ваши объекты при срабатывании таймера. Обрабатывайте ее последовательно. Что-то останавливать/запускать - лишние затраты ресурсов если много объектов.
ava
Экскалупатор | 01.01.2010, 22:11 #
Цитата (Heinzz @ 1.1.2010, 20:32 findReferencedText)
я бы сделал иначе.

может быть. лично я всегда против n потоков. чаще всего этого не требуется. но что бы судить о чем то нужно знать суть задачи. например, было бы не плохо уточнить по какому принципу срабатывают таймеры. и может быть их можно переделать в какой то алгоритм, который бы высчитывал какой кусок кода запускать и когда. и попробовать реализовать все это в одном потоке. тогда вопрос остановки остальных таймеров отпал бы сам собой.
ava
DragonFire | 02.01.2010, 15:13 #
Очередь не подойдет, так как моделируется псевдореальное время.

Задача такая: есть СМО (система массового обслуживания). В случайные моменты времени в систему приходят клиенты (поток поступления клиентов, со непредсказуемым временем срабатывания), которые обрабатываются мастерами (еще N потоков, у каждого свое непредсказуемое время срабатывания).

Проблема в том, что при срабатывании какого-либо события выполняется код, которые отнимает некое время. Из-за этого клиент, который должен был придти через 4 еденицы времени, приходит через 5 едениц (т.к. когда он пришел, выполнялся некий посторонний код).

Из-за таких накладок получается мешанина событий несвязанный нормально. Нуобходимо перед выполнением любого сложного кода блокировать все остальные таймеры, чтобы не смешивать "время из предметной области, за которое отвечают таймеры" и "симтемное время, которое тратится на выполнение кода".
ava
Экскалупатор | 02.01.2010, 15:29 #
как я уже говорил:
Цитата (Экскалупатор @ 1.1.2010, 19:37 findReferencedText)
Создай класс, который в отдельном потоке будет управлять всеми остальными потоками.

т.е. этот класс должен знать все об остальных потоках, и когда срабатывает таймер одного из потока он(класс) должен заблокировать все остальные, кроме того который сработал. потом этот класс должен дождаться завершения выполнения кода, и снова запустить все потоки.
но это несколько не понятно. ведь по сути клиент может прийти в любое время, и во время выполнения твоего кода, как тогда быть?
ava
DragonFire | 02.01.2010, 16:37 #
В том то и дело, что поток прихода клиента должен быть просто заморожен на время выполнения кода smile Чтобы не возникало таких ситуаций...
ava
kobra | 02.01.2010, 17:46 #
мне кажется что постановка задачи не коректна, или задача невыполнима.
если кажды клиент может воити в систему когда угодно (чтобы была емуляция реального времени), значит нелзя блокировать его.
но если не блокировать, то произаидет мешанина событий.
взаимо исклучающие условия
ava
Экскалупатор | 02.01.2010, 17:54 #
DragonFire, ну тогда делай через класс, который будет управлять всем остальным. но как уже сказали, весьма странное условие. лучше все таки очередь(ИМХО).
ava
DragonFire | 03.01.2010, 02:27 #
Все оказалось просто:

//Клиент
public class Client
{
//Время прихода
public Double ComingTime;
//Текущее время
public Double NowTime;
//Таймер
private Timer Timer;
private Stopwatch Stopwatch;

public event EventHandler Coming;

public Client()
{
Timer = new Timer();
Timer.AutoReset = false;
Timer.Elapsed += new ElapsedEventHandler(Timer_Elapsed);
Stopwatch = new Stopwatch();
}

public void NewClient(Double NowTime, Double ComingTime)
{
this.NowTime = NowTime;
this.ComingTime = ComingTime;
Timer.Interval = ComingTime * Setup.M;
Stopwatch.Reset();
Timer.Start();
Stopwatch.Start();
}

public void Pause()
{
Stopwatch.Stop();
Timer.Stop();
}

public void Resume()
{
Timer.Interval = ComingTime * Setup.M - Stopwatch.ElapsedMilliseconds / Setup.M;
Timer.Start();
Stopwatch.Start();
}

public void Stop()
{
Timer.Stop();
Stopwatch.Stop();
}


private void Timer_Elapsed(object sender, ElapsedEventArgs e)
{
NowTime += ComingTime;
if (Coming != null)
Coming(this, EventArgs.Empty);
}
}

...

void Client_Coming(object sender, EventArgs e)
{
Client.Pause();

РЕСУРСОЕМКИЙ КОД

Client.Resume();
}

Смысл в добавление Stopwatсh чтобы отследить время работы таймера....
Зарегистрируйтесь или войдите, чтобы написать.
Фирма дня
Вы также можете добавить свою фирму в каталог IT-фирм, и публиковать статьи, новости, вакансии и другую информацию от имени фирмы.
Подробнее
Участники
advanced
Отправить