powered by simpleCommunicator - 2.0.61     © 2026 Programmizd 02
Целевая тема:
Создать новую тему:
Автор:
Закрыть
Цитировать
Форумы / Delphi [игнор отключен] [закрыт для гостей] / Как правильно заморозить поток из самого себя?
25 сообщений из 74, страница 1 из 3
Как правильно заморозить поток из самого себя?
    #40050066
Фотография X11
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Программа рассылки сообщений корпоративным пользователям компании должна рассылать сообщения только в определенное время, например, с 8 утра до 18 часов вечера.
Так вот, такой код просто загружает проц на 15%
Код: pascal
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
12.
13.
14.
15.
16.
17.
18.
19.
20.
21.
22.
23.
procedure TSendNotifyThread.Execute;
begin
...
...

// fTimeStartNotyfy - время начал рассылок
// fTimeStopNotyfy - время окончания рассылок
// System.SysUtils.Time - текущее время
// fSendNotifyInerval - интервал рассылки, каждые 5 сек.


  while not Terminated do
  begin
    try
      if Terminated then Break;

      // рассылка разрешена только в указанное время
      if (System.SysUtils.Time <= fTimeStartNotyfy) or (System.SysUtils.Time >= fTimeStopNotyfy) then
        Continue;// пропускаем цикл если время не подходящее

      if WaitForSingleObject(FTerminateEvent, fSendNotifyInerval) <> WAIT_ABANDONED then 
      begin
// рассылка сообщений



т.е. вместо Continue нужно поставить
Код: pascal
1.
WaitForSingleObject(FTerminateEvent, XXX);


XXX - это количество миллисекунд до 8 утра, когда настанет резрешенное время.

или я все равно неправильно сделаю?

Подскажите, как правильно усыпить поток и запустить из самого себя, так сказать?
Ну и переписывать это всё не хочется.

Спасибо.
...
Рейтинг: 0 / 0
Как правильно заморозить поток из самого себя?
    #40050070
Фотография _Vasilisk_
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
X11
т.е. вместо Continue нужно поставить
Код: pascal
1.
WaitForSingleObject(FTerminateEvent, XXX);



XXX - это количество миллисекунд до 8 утра, когда настанет резрешенное время.
Это один из вариантов. Второй использовать WaitableTimer и ждать двух событий: либо таймер, либо сообщения на завершение программы
X11
Код: pascal
1.
 if WaitForSingleObject(FTerminateEvent, fSendNotifyInerval) <> WAIT_ABANDONED then 

Почитай что такое WAIT_ABANDONED. Это точно не то, что тебе нужно
...
Рейтинг: 0 / 0
Как правильно заморозить поток из самого себя?
    #40050073
Фотография X11
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
_Vasilisk_
Почитай что такое WAIT_ABANDONED. Это точно не то, что тебе нужно


неа, пока не понял..
...
Рейтинг: 0 / 0
Как правильно заморозить поток из самого себя?
    #40050075
Фотография X11
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
_Vasilisk_
использовать WaitableTimer

это оно?

https://gist.github.com/perevoznyk/1f554a2bd4b7523701c6d9e26dc7a473
...
Рейтинг: 0 / 0
Как правильно заморозить поток из самого себя?
    #40050077
Фотография _Vasilisk_
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
X11
неа, пока не понял..
Это отказ соседнего процесса от мьютекса
...
Рейтинг: 0 / 0
Как правильно заморозить поток из самого себя?
    #40050079
Фотография _Vasilisk_
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
X11
это оно?
Функции те, но код страшный. MsgWaitForMultipleObjects не нужен точно. Достаточно будет WaitForMultipleObjects. И liDueTime.QuadPart тебе удобнее будет использовать положительный. Так сразу можно установить время срабатывания
...
Рейтинг: 0 / 0
Как правильно заморозить поток из самого себя?
    #40050084
YuRock
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
_Vasilisk_
X11
это оно?
Функции те, но код страшный. MsgWaitForMultipleObjects не нужен точно. Достаточно будет WaitForMultipleObjects. И liDueTime.QuadPart тебе удобнее будет использовать положительный. Так сразу можно установить время срабатывания

В общем-то для этой задачи достаточно одного обычного эвента (который уже есть). Ждать по 60 секунд, после ожидания - проверять Terminated, если не выход - проверять насписание, если пора - отправлять почту, нет - Continue.
...
Рейтинг: 0 / 0
Как правильно заморозить поток из самого себя?
    #40050085
YuRock
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
X11
_Vasilisk_
Почитай что такое WAIT_ABANDONED. Это точно не то, что тебе нужно


неа, пока не понял..
Если на что-то и проверять - то разве что на WAIT_FAILED, для логирования логических ошибок разработки.
А так - не важно, что он вернет - таймаут или сработку - на Terminated проверять всё равно надо и лучше.
...
Рейтинг: 0 / 0
Как правильно заморозить поток из самого себя?
    #40050087
asutp2
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
X11,

а чем тебя не устраивают паузы в стиле:
Код: pascal
1.
2.
    ServiceThread.ProcessRequests(False);
    Sleep(10);

Проц не грузит, служба не зависает...
...
Рейтинг: 0 / 0
Как правильно заморозить поток из самого себя?
    #40050091
rgreat
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Sleep(1000) перед Continue да и все.
...
Рейтинг: 0 / 0
Как правильно заморозить поток из самого себя?
    #40050093
Dimitry Sibiryakov
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
asutp2Проц не грузит

Ещё как грузит, просто ты за своими гигагерцами это не замечаешь. Посмотри в
ProcessExplorer счётчики переключения контекстов.
Posted via ActualForum NNTP Server 1.5
...
Рейтинг: 0 / 0
Как правильно заморозить поток из самого себя?
    #40050100
asutp2
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Dimitry Sibiryakov

asutp2Проц не грузит

Ещё как грузит, просто ты за своими гигагерцами это не замечаешь. Посмотри в
ProcessExplorer счётчики переключения контекстов.
Когда диспетчер задач непрерывно показывает ЦП 0% у сервиса с подобной реализацией простоя, действительно сложно заметить :-)
...
Рейтинг: 0 / 0
Как правильно заморозить поток из самого себя?
    #40050131
Фотография X11
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
X11
_Vasilisk_
использовать WaitableTimer

это оно?

https://gist.github.com/perevoznyk/1f554a2bd4b7523701c6d9e26dc7a473


такс... а тут используется Application.ProcessMessages;
а для потоков это норм?
...
Рейтинг: 0 / 0
Как правильно заморозить поток из самого себя?
    #40050133
Фотография X11
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
_Vasilisk_
И liDueTime.QuadPart тебе удобнее будет использовать положительный. Так сразу можно установить время срабатывания


Т.е. просто минус убрать?
или еще что-то менять надо?


И что значит "Так сразу можно установить время срабатывания"?
...
Рейтинг: 0 / 0
Как правильно заморозить поток из самого себя?
    #40050134
Фотография makhaon
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
X11


такс... а тут используется Application.ProcessMessages;
а для потоков это норм?

это почти везде не норм, а для потоков это мрак и дичь.
...
Рейтинг: 0 / 0
Как правильно заморозить поток из самого себя?
    #40050136
Фотография X11
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
т.е. ту функцию уже точно нельзя использовать.

другие советы тоже под вопросом?
...
Рейтинг: 0 / 0
Как правильно заморозить поток из самого себя?
    #40050146
Фотография makhaon
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
...
Рейтинг: 0 / 0
Как правильно заморозить поток из самого себя?
    #40050152
white_nigger
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
А виндовый планировщик не хочешь использовать?
...
Рейтинг: 0 / 0
Как правильно заморозить поток из самого себя?
    #40050157
Фотография X11
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
мне бы что-то попроще

потому что наворотить такой код, в котором я долго не смогу разобраться и понять, что там к чему, не очень хотелось бы
...
Рейтинг: 0 / 0
Как правильно заморозить поток из самого себя?
    #40050164
s62
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Можно так:
Код: pascal
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
12.
13.
14.
15.
16.
17.
18.
19.
20.
21.
22.
23.
24.
procedure TSendNotifyThread.Execute;
begin
...

// fTimeStartNotyfy - время начал рассылок
// fTimeStopNotyfy - время окончания рассылок
// System.SysUtils.Time - текущее время
// fSendNotifyInerval - интервал рассылки, каждые 5 сек.


  while not Terminated do
  begin
    try
      if Terminated then Break;

      // рассылка разрешена только в указанное время
      case WaitForSingleObject(FTerminateEvent, fSendNotifyInerval) of // fSendNotifyInerval = 5000 мсек
        WAIT_OBJECT_0: break;
        WAIT_TIMEOUT: if (System.SysUtils.Time > fTimeStartNotyfy) and (System.SysUtils.Time < fTimeStopNotyfy)
          then
    // рассылка сообщений
        WAIT_FAILED: //обработка ошибки
     end;
...
...
Рейтинг: 0 / 0
Как правильно заморозить поток из самого себя?
    #40050165
Фотография X11
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
X11
_Vasilisk_
использовать WaitableTimer

это оно?

https://gist.github.com/perevoznyk/1f554a2bd4b7523701c6d9e26dc7a473


когда задействовал эту функцию Wait()

то madExcept по завершеню работы программы выдал просто ТУЧУ resource leaks
...
Рейтинг: 0 / 0
Как правильно заморозить поток из самого себя?
    #40050171
Фотография ну я
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
X11

Так вот, такой код просто загружает проц на 15%
Код: pascal
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
  while not Terminated do
  begin
    try
      if Terminated then Break;

      // рассылка разрешена только в указанное время
      if (System.SysUtils.Time <= fTimeStartNotyfy) or (System.SysUtils.Time >= fTimeStopNotyfy) then
        Continue;// пропускаем цикл если время не подходящее

// рассылка сообщений



Такой код грузит свое ядро на 100%.
А то что винда показывает около 15 - так это потому что проц многоядерный.
15% примерно соответствует Intel Core i7.
...
Рейтинг: 0 / 0
Как правильно заморозить поток из самого себя?
    #40050184
Фотография X11
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
ProcessExplorer

Код: pascal
1.
2.
3.
4.
5.
      if (System.SysUtils.Time <= fTimeStartNotyfy) or (System.SysUtils.Time >= fTimeStopNotyfy) then
      begin
        Sleep(1000);
        Continue;// пропускаем цикл если время не подходящее
      end;
...
Рейтинг: 0 / 0
Как правильно заморозить поток из самого себя?
    #40050186
Фотография wadman
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Ох...

Не грузит процессор, ожидает сообщения, минимум памяти, без обратной связи (но сделать просто).
Можно сделать массив с 1000 потоками и раскидывать между ними сообщения.
Расписание нужно организовывать в основном потоке, а эти - только для работы/отправки.

Код: pascal
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
12.
13.
14.
15.
16.
17.
18.
19.
20.
21.
22.
23.
24.
25.
26.
27.
28.
29.
30.
31.
32.
33.
34.
35.
36.
37.
38.
39.
40.
41.
42.
43.
44.
45.
46.
47.
48.
49.
50.
51.
52.
53.
54.
55.
56.
57.
58.
59.
60.
61.
62.
63.
64.
65.
66.
67.
68.
69.
70.
71.
72.
73.
74.
75.
76.
77.
78.
79.
80.
81.
82.
83.
84.
85.
86.
87.
88.
89.
90.
91.
92.
93.
94.
95.
96.
97.
98.
99.
100.
101.
102.
103.
104.
105.
106.
107.
108.
109.
110.
111.
112.
113.
program Project1;

{$APPTYPE CONSOLE}

uses
  SysUtils,
  Windows;

type
  PThreadRecord = ^TThreadRecord;
  TThreadRecord = record
  private
    FHandle: THandle;
    FID: Cardinal;
    FNextMessage: Pointer;
    FEvent: THandle;
    FStopping: boolean;
  public
    function Start: boolean;
    function Enqueue(const AMessage: Pointer): boolean;
    function IsRinnung: boolean;
    function Stop: boolean;
  end;

{ TThreadRecord }

function ThreadMainLoop(Instance: Pointer): Integer;
begin
  result := 0;
  with PThreadRecord(Instance)^ do begin
    while not FStopping do begin
      if (WaitForSingleObject(FEvent, INFINITE) = 0) and (not FStopping) then begin
        ResetEvent(FEvent);
        if Integer(FNextMessage) <> -1 then begin
          Sleep(100); // working
        end;
        Integer(FNextMessage) := -1;
      end;
    end;
    CloseHandle(FEvent);
    FEvent := 0;
    CloseHandle(FHandle);
    FHandle := 0;
  end;
end;

function TThreadRecord.Enqueue(const AMessage: Pointer): boolean;
begin
  result := false;
  if LongBool(FHandle) and (not IsRinnung) then begin
    result := InterlockedCompareExchange(Integer(FNextMessage), Integer(AMessage), -1) = -1;
    if result then
      result := SetEvent(FEvent);
  end;
end;

function TThreadRecord.IsRinnung: boolean;
begin
  result := (FHandle > 0) and (not FStopping) and (Integer(FNextMessage) <> -1);
end;

function TThreadRecord.Start: boolean;
begin
  FHandle := 0;
  result := false;
  FEvent := CreateEvent(nil, true, false, '');
  if not LongBool(FEvent) then exit;
  Integer(FNextMessage) := -1;
  FStopping := false;
  FHandle := BeginThread(nil, 2*1024*1024, @ThreadMainLoop, @Self, $10000, FID);
  result := Fhandle > 0;
  if not result then begin
    CloseHandle(FEvent);
    FEvent := 0;
  end;
end;

function TThreadRecord.Stop: boolean;
begin
  FStopping := true;
  SetEvent(FEvent);
  result := true;
end;

var
  thread: TThreadRecord;
  p: integer;
  //m: Pointer;

begin
  ReportMemoryLeaksOnShutdown := true;
  //GetMem(m, 1024); // test for leaks
  try
    if thread.Start then begin
      Writeln('Started');
      p := $10;
      if thread.Enqueue(Pointer(p)) then Writeln('Enqueued ', IntToHex(p, 4));
      p := $12;
      if thread.Enqueue(Pointer(p)) then Writeln('Enqueued ', IntToHex(p, 4));
      p := $20;
      if thread.Enqueue(Pointer(p)) then Writeln('Enqueued ', IntToHex(p, 4));
      sleep(1000);
      p := $30;
      if thread.Enqueue(Pointer(p)) then Writeln('Enqueued ', IntToHex(p, 4));
      sleep(1000);
      if thread.Stop then writeln('Stoped');
    end;
  except
    on E:Exception do
      Writeln(E.Classname, ': ', E.Message);
  end;
  readln;
end.

...
Рейтинг: 0 / 0
Как правильно заморозить поток из самого себя?
    #40050189
Фотография X11
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Мне не надо раскидывать между потоками сообщения (пока что).
Нужно (пока что) приостановить поток, а потом продолжить его работу.
Из самого себя.
...
Рейтинг: 0 / 0
25 сообщений из 74, страница 1 из 3
Форумы / Delphi [игнор отключен] [закрыт для гостей] / Как правильно заморозить поток из самого себя?
Найденые пользователи ...
Разблокировать пользователей ...
Читали форум (0):
Пользователи онлайн (0):
x
x
Закрыть


Просмотр
0 / 0
Close
Debug Console [Select Text]