Гость
Целевая тема:
Создать новую тему:
Автор:
Форумы / Delphi [игнор отключен] [закрыт для гостей] / Как правильно заморозить поток из самого себя? / 25 сообщений из 74, страница 1 из 3
03.03.2021, 00:06
    #40050066
X11
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
03.03.2021, 00:12
    #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
03.03.2021, 00:16
    #40050073
X11
X11
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Как правильно заморозить поток из самого себя?
_Vasilisk_
Почитай что такое WAIT_ABANDONED. Это точно не то, что тебе нужно


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

это оно?

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

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


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

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

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

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

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

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

это оно?

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


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


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


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


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

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

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

потому что наворотить такой код, в котором я долго не смогу разобраться и понять, что там к чему, не очень хотелось бы
...
Рейтинг: 0 / 0
03.03.2021, 10:46
    #40050164
s62
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
03.03.2021, 10:48
    #40050165
X11
X11
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Как правильно заморозить поток из самого себя?
X11
_Vasilisk_
использовать WaitableTimer

это оно?

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


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

то madExcept по завершеню работы программы выдал просто ТУЧУ resource leaks
...
Рейтинг: 0 / 0
03.03.2021, 11:02
    #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
03.03.2021, 11:20
    #40050184
X11
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
03.03.2021, 11:21
    #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
03.03.2021, 11:23
    #40050189
X11
X11
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Как правильно заморозить поток из самого себя?
Мне не надо раскидывать между потоками сообщения (пока что).
Нужно (пока что) приостановить поток, а потом продолжить его работу.
Из самого себя.
...
Рейтинг: 0 / 0
Форумы / Delphi [игнор отключен] [закрыт для гостей] / Как правильно заморозить поток из самого себя? / 25 сообщений из 74, страница 1 из 3
Найденые пользователи ...
Разблокировать пользователей ...
Читали форум (0):
Пользователи онлайн (0):
x
x
Закрыть


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