Форум программистов
 

Восстановите пароль или Зарегистрируйтесь на форуме, о проблемах и с заказом рекламы пишите сюда - alarforum@yandex.ru, проверяйте папку спам!

Вернуться   Форум программистов > Низкоуровневое программирование > Win Api
Регистрация

Восстановить пароль
Повторная активизация e-mail

Купить рекламу на форуме - 42 тыс руб за месяц

Ответ
 
Опции темы Поиск в этой теме
Старый 25.09.2012, 17:56   #1
Человек_Борща
Старожил
 
Аватар для Человек_Борща
 
Регистрация: 30.12.2009
Сообщений: 11,426
Счастье Контролируемый Sleep потока.

Доброго времени суток!

Имеется поток(TThread в Delphi, навесной класс для CreateThread из набора функций винды).
Поток работает от начала старта программы и до её завершения, без перерыва и остановок(Suspend, Resume).
Проблема в том, что серверу нужно отдохнуть от запросов т.к. программа будет популярна и сис. админы будут отдавать сотни ненависти к тому, кто дал юзерам возможность засорять канал сервера постоянной передачей POST|GET запросов с 50% возможностью получения одной и той же инфы в течении 30 сек.

Чтобы такого не было, было принято автоматом тормозить поток при помощи Sleep на N секунд(минимально 60 сек). И этого помогло.

Однако, поток работает постоянно, и если юзер решает её закрыть(программу), то программа вешается, т.к. ждет, пока поток выспится, и прыгнет в условие:
Код:
if terminated then exit;
Юзеров не радует, что программа виснет при выходе на 1 минуту.


Как прервать спячку потока и завершить его?
Человек_Борща вне форума Ответить с цитированием
Старый 25.09.2012, 18:26   #2
Аватар
Старожил
 
Аватар для Аватар
 
Регистрация: 17.11.2010
Сообщений: 18,922
По умолчанию

Заменить длинный sleep на серию коротких в цикле и там проверять terminated. Не надеяться на точность отсчета времени и в цикле еще системное время проверять, что бы закончить его через заданное к-во секунд
Если бы архитекторы строили здания так, как программисты пишут программы, то первый залетевший дятел разрушил бы цивилизацию
Аватар вне форума Ответить с цитированием
Старый 25.09.2012, 19:41   #3
Человек_Борща
Старожил
 
Аватар для Человек_Борща
 
Регистрация: 30.12.2009
Сообщений: 11,426
По умолчанию

Не вариант. Нужно редактировать время сна.
Человек_Борща вне форума Ответить с цитированием
Старый 25.09.2012, 19:42   #4
veniside
Старожил
 
Регистрация: 03.01.2011
Сообщений: 2,508
По умолчанию

я бы слип заменил на

Код:
  WaitForSingleObject(event, 60*1000);
если надо прервать сон, просто устанавливаем even в signaled состояние.
"Когда приходит положенное время, человек перестаёт играть в пинбол. Только и всего."
veniside вне форума Ответить с цитированием
Старый 25.09.2012, 20:00   #5
Аватар
Старожил
 
Аватар для Аватар
 
Регистрация: 17.11.2010
Сообщений: 18,922
По умолчанию

Цитата:
Нужно редактировать время сна
Чем принципиально редактирование времени сна для длинного sleep и серии коротких в цикле отличается? Или для WaitForSingleObject?
Если бы архитекторы строили здания так, как программисты пишут программы, то первый залетевший дятел разрушил бы цивилизацию
Аватар вне форума Ответить с цитированием
Старый 25.09.2012, 22:01   #6
Человек_Борща
Старожил
 
Аватар для Человек_Борща
 
Регистрация: 30.12.2009
Сообщений: 11,426
По умолчанию

veniside, вариант, НО работать так же должно как sleep. Имеется ввиду автономно, без внешнего "Да ты, сейчас можешь спать", и одновременно из вне с "Ты должен сейчас повесится".
Вот кусок кода, где нужно усыплять поток:
Код:
          while not Terminated do
          begin

          {$REGION 'Говнокод.rar'}
            if not bIsFirst then // Первый раз ждать не надо!
            begin
              //Слип - 60 сек.
              Sleep(2500);
              if Terminated then
                goto gothis;
              Sleep(2500);
              if Terminated then
                goto gothis;
              Sleep(2500);
              if Terminated then
                goto gothis;
              Sleep(2500);
              if Terminated then
                goto gothis;
              Sleep(2500);
              if Terminated then
                goto gothis;
              Sleep(2500);
              if Terminated then
                goto gothis;
              Sleep(2500);
              if Terminated then
                goto gothis;
              Sleep(2500);
              if Terminated then
                goto gothis;
              Sleep(2500);
              if Terminated then
                goto gothis;
              Sleep(2500);
              if Terminated then
                goto gothis;
              Sleep(2500);
              if Terminated then
                goto gothis;
              Sleep(2500);
              if Terminated then
                goto gothis;
              Sleep(2500);
              if Terminated then
                goto gothis;
              Sleep(2500);
              if Terminated then
                goto gothis;
              Sleep(2500);
              if Terminated then
                goto gothis;
              Sleep(2500);
              if Terminated then
                goto gothis;
              Sleep(2500);
              if Terminated then
                goto gothis;
              Sleep(2500);
              if Terminated then
                goto gothis;
              Sleep(2500);
              if Terminated then
               goto gothis;
              Sleep(2500);
              if Terminated then
              goto gothis;
              Sleep(2500);
              if Terminated then
             goto gothis;
              Sleep(2500);
              if Terminated then
              goto gothis;
              Sleep(2500);
              if Terminated then
              goto gothis;
              Sleep(2500);
              if Terminated then
              goto gothis;


              { if fSleepTime < cSleep_Min then
                Sleep(cSleep_Min * 1000)
                else
                begin
                if fSleepTime > cSleep_Max then
                Sleep(cSleep_Max * 1000)
                else
                Sleep(fSleepTime * 1000);
                end; }
            end;
          {$ENDREGION}

            gothis:
            // Надо выйти
            if fLogined and fDoLogout and (not fLogouted) then
            begin
              fLogined := False;
              fDoLogout := False;
              fLogouted := True;
              fHTTP.Clear;
              fHTTP.Cookies.Clear;
              SetLogin(lrLogouted);
              fEvent.ResetEvent;
              Break; // Выйти из цикла inner while
            end;


{
more code... 
}

            bIsFirst := False; // Первый заход сделан =)
          end;                 // inner while end
Что-то вроде таймера, во время работы которого поток спит, и пока он спит, может прийти сообщение "Хватит спать, отмирай, юзер вырубает программу"

Последний раз редактировалось Человек_Борща; 25.09.2012 в 22:09.
Человек_Борща вне форума Ответить с цитированием
Старый 25.09.2012, 23:08   #7
waleri
Старожил
 
Регистрация: 13.07.2012
Сообщений: 6,330
По умолчанию

Что плохого в циклах?
waleri вне форума Ответить с цитированием
Старый 26.09.2012, 00:14   #8
Человек_Борща
Старожил
 
Аватар для Человек_Борща
 
Регистрация: 30.12.2009
Сообщений: 11,426
По умолчанию

Плохо то, что общее время простоя, с каждой интерацией, цикла будет больше... Итого, когда цикл от 1 до 60,достигнет 60-го витка, поток, в общем, проспит 11 925 446 милисекунд, когда надо всего-то 60 000 мс.
Человек_Борща вне форума Ответить с цитированием
Старый 26.09.2012, 06:49   #9
waleri
Старожил
 
Регистрация: 13.07.2012
Сообщений: 6,330
По умолчанию

Цитата:
Сообщение от Человек_Борща Посмотреть сообщение
в общем, проспит 11 925 446 милисекунд, когда надо всего-то 60 000 мс.
С чего вы взяли?
waleri вне форума Ответить с цитированием
Старый 26.09.2012, 08:32   #10
Аватар
Старожил
 
Аватар для Аватар
 
Регистрация: 17.11.2010
Сообщений: 18,922
По умолчанию

Откуда 11 925 446? Почти те же 60 000. Большая точность здесь ни к чему. Если уж надо, то цикл WHILE или REPEAT и в теле цикла контролировать время прошедшее с начала цикла, хотя не думаю что точней на много получится
Код:
for i:=1 to 30 do begin
  Sleep(2000);
  if Terminated then Break;
end;
if Terminated then goto gothis;
Если бы архитекторы строили здания так, как программисты пишут программы, то первый залетевший дятел разрушил бы цивилизацию

Последний раз редактировалось Аватар; 26.09.2012 в 08:43.
Аватар вне форума Ответить с цитированием
Ответ


Купить рекламу на форуме - 42 тыс руб за месяц



Похожие темы
Тема Автор Раздел Ответов Последнее сообщение
Должно быть 3 потока. А диспетчер задач показывает, что потока создано 2 BEL9ILLI Общие вопросы Delphi 3 06.12.2011 20:26
Sleep в потоке Florento Общие вопросы Delphi 13 21.06.2011 21:54
Как узнать номер потока из самого потока? GaMeSTeR Помощь студентам 0 03.12.2010 09:50
Sleep(50); за 63 мс... или за 47... Teksa Общие вопросы C/C++ 8 20.07.2010 08:34
контролируемый ввод Kandela Assembler - Ассемблер (FASM, MASM, WASM, NASM, GoASM, Gas, RosAsm, HLA) и не рекомендуем TASM 2 20.05.2008 23:32