![]() |
| ||
|
|
Новости |
Поиск |
FAQ |
Статьи |
Книги |
Новости VCL
| | Форумы ЧАТ |
Орешник |
|
| |||
| |||
« предыдущая ветвь | форум | следующая ветвь »
есть ли фанкция аналог sleep для своего потока ?
ali_tash © (2005-02-08 21:52:00)как я понял Sleep(1000) запрещает выполнятся главному потоку приложения на 1000 мс
а как можно запретить своему созданному потоку не работать какой нибудь интервал времени
Suspend замораживает поток но потом его надо Resumiть.
можно конечно использовать таймер , но как то не красиво
sniknik (2005-02-12 02:51:00) [1]> Это каким образом повышение приоритета добавляет время ожидания ?
имелось ввиду при сравнении потоков с разными приоритетами, низкий будет ждать дольше (сказано чтобы исключить их из рассматривания, т.к. они все усложняют, а зачем это?), с высоким получает в первую очередь с низким "через раз", правильно? а вот если идут сплош задания с высокими приоритетами то низкому система временно повышает его, чтобы он совсем не у дел не оставался.
чтото типа этого, не специалист в этом, т.что точную картину "нарисовать" не могу (вернее могу но неохота углублятся в разбор ненужной области), но смысл верен.
> Из серии: в военное время синус до 5 доходит ?
> Ты бы лучше выложил код, который показывает, что поток, обратившийся к sleep(0) ждет больше секунды.
ну да, а косинус 18ти.
без проблем, простой перенос в код теоретической ситуации из -> sniknik © (11.02.05 17:11) [24]
unit ThreadUnit;
interface
uses
Classes, Windows, SysUtils, StdCtrls;
type
TFoolThread = class(TThread)
private
fFool, fShow: boolean;
fLabel: TLabel;
MaxWait: integer;
protected
procedure UpdateLabel;
procedure Execute; override;
public
constructor Create(nLabel: TLabel; nFool, nShow: boolean);
end;
implementation
constructor TFoolThread.Create(nLabel: TLabel; nFool, nShow: boolean);
begin
fFool:= nFool;
fShow:= nShow;
fLabel:= nLabel;
FreeOnTerminate:= true;
inherited Create(False);
end;
procedure TFoolThread.UpdateLabel;
begin
fLabel.Caption:= IntToStr(MaxWait);
end;
procedure TFoolThread.Execute;
var
i, CycleCount: integer;
StartMs, CountMs: integer;
begin
MaxWait:= 0;
CycleCount:= 100;
while (not Terminated) and (CycleCount > 0) do begin
if fFool then begin
for i:= Low(Integer) to High(Integer) do ;
end else begin
StartMs:= GetTickCount();
sleep(0);
CountMs:= GetTickCount() - StartMs;
if CountMs > MaxWait then MaxWait:= CountMs;
end;
Dec(CycleCount);
end;
if fShow then Synchronize(UpdateLabel);
end;
end.
и вызовы
procedure TForm1.Button1Click(Sender: TObject);
var i: integer;
begin
for i:= 1 to 128 do
TFoolThread.Create(Label1, false, false);
TFoolThread.Create(Label1, false, true);
end;
procedure TForm1.Button2Click(Sender: TObject);
var i: integer;
begin
for i:= 1 to 128 do
TFoolThread.Create(Label1, true, false);
TFoolThread.Create(Label1, false, true);
end;
первая кнопка у меня выдала 80 мс, вторая (кстати предупреждаю очень длительная "операция", с практически полным повисанием системы надолго, даже после получения результата) 24656 мс (что согласитесь гораздо больше секунды)
Leonid Troyanovsky (2005-02-12 00:58:00) [2]
> Игорь Шевченко © (11.02.05 17:55) [25]
> Ты бы лучше выложил код, который показывает, что поток,
> обратившийся к sleep(0) ждет больше секунды.
На двухпроцессорном w2k3 в Button2Click ждет и более 1 сек
(можно подобрать maxi)
type
TWorkThread = class(TThread)
procedure Execute; override;
end;
const
maxi = 100000000;
procedure TWorkThread.Execute;
var
i: Longint;
begin
Priority := tpHighest;
ReturnValue := 0;
for i := 0 to maxi do
if Terminated then
Break
else
ReturnValue := (ReturnValue + 1) mod maxi;
end;
var
t1, t2: TWorkThread;
procedure TForm1.Button1Click(Sender: TObject);
begin
t1 := TWorkThread.Create(False);
t2 := TWorkThread.Create(False);
end;
procedure TForm1.Button2Click(Sender: TObject);
var
t : Longint;
begin
t := GetTickCount;
SetThreadPriority(GetCurrentThreadId, THREAD_PRIORITY_LOWEST);
Sleep(0);
SetThreadPriority(GetCurrentThreadId, THREAD_PRIORITY_NORMAL);
Caption := IntToStr(GetTickCount-t);
t1.Free;
t2.Free;
end;
Происходящее не очень удивительно, бо описано у Соломона-
Русиновича и, вроде, даже у Рихтера. Но, читать лениво,
а вспомнить могу лишь то, что давно не работавшим потокам
хоть и повышают приоритет, но не намного (на 2, кажись).
--
Regards, LVT.
Игорь Шевченко (2005-02-11 17:55:00) [3]sniknik © (11.02.05 17:11) [24]
> приоритет только запутывает, тем более система все равно
> повысит приоритет у давно ожидаюшего потока. т.что это только
> немного добавит времени к ожиданию
Это каким образом повышение приоритета добавляет время ожидания ?
> вся куча использует для задержки цикл
> for i:= Low(Int64) to High(Int64) do ; (и так несколько
> раз на нужное количество мс)
А какая разница, через квант все равно поток прервется и будет диспетчеризация.
> вариант есть может и на больше задержатся чем на секунду
Из серии: в военное время синус до 5 доходит ?
Ты бы лучше выложил код, который показывает, что поток, обратившийся к sleep(0) ждет больше секунды.
sniknik (2005-02-11 17:11:00) [4]Игорь Шевченко © (09.02.05 11:19) [5]
>> даже Sleep(0) может перекрыть интервал в 1000 мс
> Точно ?
а чего не точно, конечно точно, вариант есть может и на больше задержатся чем на секунду.
ну к примеру куча равноправных потоков (приоритет только запутывает, тем более система все равно повысит приоритет у давно ожидаюшего потока. т.что это только немного добавит времени к ожиданию (примем эту поправку коэффицентом ;о)))
ну вот, куча равноправных, у всех режим ожидания стоит sleep(0), можно прикинуть ожидаемое время будет приблизительно одинаковым. (никто ничего не делает, только система занята распределяет время "работы")
а теперь другая ситуация (кстати реальная, код такой видел) вся куча использует для задержки цикл
for i:= Low(Int64) to High(Int64) do ; (и так несколько раз на нужное количество мс)
и только один "добрый" сделал sleep(0)...
???
я лично затрудняюсь сказать на сколько времени будет в этом случае задержка у sleep-а. то что он получит управление, и даже до того как остальные закончат без вопросов, система постарается а вот время на которое прервется?
(естественно ситуация утрирована, просто показать максимальную загрузку)
Marser (2005-02-10 18:06:00) [5]
> Digitman © (09.02.05 15:30) [13]
А что? Интересный вариант...
ali_tash (2005-02-10 17:43:00) [6]спасибо
Digitman (2005-02-10 08:24:00) [7]"прос ыпаться" - это я лихо задвинул)
"проснуться" конечно же !
Digitman (2005-02-10 08:23:00) [8]
> ali_tash (09.02.05 19:32) [15]
> можеш привести пример ?
hEvent := CreateEvent(nil, false, false, nil);
try
case MsgWaitForMultipleObjects(1, hEvent, False, 1000, QS_ALLINPUT) of
WAIT_OBJECT_0: ..//просигналил ивент, пора просыпаться и работать дальше
WAIT_OBJECT_0 + 1:..//поступило сообщение, пора просыпаться и обработать его
WAIT_TIMEOUT: //спали секунду, за эту секунду ничего не произошло, пора просыпаться и работать дальше
finally
CloseHandle(hEvent);
end;
Alexander Panov (2005-02-09 23:04:00) [9]ali_tash (09.02.05 21:39) [17]
Synchronize используется для выполнения кода в основном потоке, что ты успешно и делаешь непрерывно.
Пример можешь посмотреть вот здесь:
http://www.delphimaster.ru/cgi-bin/forum.pl?id=1107978628&n=5
В примере не используется Synchronize, но, думаю, что дальше сам разберешься.
Alexander Panov (2005-02-09 23:02:00) [10]ali_tash (09.02.05 21:39) [17]
Твоя ошибка в коде Synchronize(DoWork);
Разберись, как работает Synchronize.
ali_tash (2005-02-09 21:39:00) [11]если я создам в своей программе поток с такими методами
procedure TMyThread1.DoWork;
begin
// например сюда Sleep(1000);
if Assigned(GOnTimer) then GOnTimer(Self);
end;
procedure TMyThread1.Execute;
begin
inherited;
while not Terminated do
Synchronize(DoWork);
end;
то когда будет срабатывать процедура sleep будет останавливаться выполнение самой программы ,а мне надо чтоб останавливался только мой поток.
а насчёт WaitForSingleObject это же процедура для паузы
программы которая запустила внешнюю программу до завершения внешней.
если я ошибаюсь то напишите пример как использовать WaitForSingleObject в моём случае.
Fay (2005-02-09 20:30:00) [12]2 Digitman © (09.02.05 15:30) [13]
Вас не затруднит пояснить, чем (в данном случае) "дурной" sleep хуже WaitForSingleObject?
ali_tash (2005-02-09 19:32:00) [13]Digitman
можеш привести пример ?
Владислав (2005-02-09 16:17:00) [14]> Игорь Шевченко © (09.02.05 15:29) [12]
К сожалению, книг этих у меня нет. Надо с этим как-то бороться :о)
Я, вообще-то, ориентировался на материалы, изложенные в книге Рихтера.
В общем, заинтриговали :)
Digitman (2005-02-09 15:30:00) [15]какие там нафих приоритеты ?
imho, вопрос автора неверно истолкован в принципе.
ибо изложен был крайне криво.
imho, автор желает в ТЕКУЩЕМ треде вызвать Suspend, при сем "заснуть беспробудным сном" и "проснуться" через N времени с того "места", где он, текущий тред, "заснул" при предыдущем Suspend ..
дурь она и есть дурь.
никто не понуждает автора вызывать Suspend дабы "заснуть с желанием проснуться через N времени" ... достаточно организовать никем (в рамках системы в целом) заведомо не "трогаемый" объект синхронизации (например, event) и вызвать вместо дурного sleep() ф-цию WaitForSingleObject(event_объект, время_ожидания_срабатывания_этого_объекта)
Игорь Шевченко (2005-02-09 15:29:00) [16]Владислав © (09.02.05 15:25) [10]
Соломон, Руссинович - Внутреннее устройство Windows 2000, глава 6, планирование потоков.
Таненбаум - Современные операционные системы, глава 2.
Marser (2005-02-09 15:25:00) [17]
> kaZaNoVa © (09.02.05 15:06) [9]
> а с приоритетами вообще ThreadProc управления не получает
> .. (
Может, critical это перебор?
Владислав (2005-02-09 15:25:00) [18]> Игорь Шевченко © (09.02.05 12:51) [7]
Ну хотя бы поясните свое мнение. Хоть ссылкой на материалы.
kaZaNoVa (2005-02-09 15:06:00) [19]а с приоритетами вообще ThreadProc управления не получает .. (
kaZaNoVa (2005-02-09 15:05:00) [20]сделал тестовую программу .. у меня в таком виде показывает в среднем 25
program Project1;
uses
Windows,SysUtils;
{$R *.res}
Var
run:boolean;
p,tk:int64;
id:cardinal;
Procedure ThreadProc;
Var num,i:cardinal;
Begin
//SetThreadPriority(GetCurrentThread, THREAD_PRIORITY_IDLE);
while not run do sleep(1); //ожидаем команды на старт
num:=GetTickCount;
i:=0;
repeat
sleep(1);
inc(i);
Until ((GetTickCount-num)>1000);
MessageBox(0,Pchar(IntToStr(i)),' ',0);
run:=false;
End;
begin
run:=false;
//SetThreadPriority(GetCurrentThread, THREAD_PRIORITY_TIME_CRITICAL);
CreateThread(nil,0,@ThreadProc,nil,0,id);
run:=true;
tk:=0;
While tk<1000000000 do tk:=tk+1;
repeat
sleep(11);
Until not run;
end.