Модераторы: Poseidon, Snowy, bems, MetalFan
  

Поиск:

Ответ в темуСоздание новой темы Создание опроса
> Не работает Synchronize в консольном приложении 
V
    Опции темы
-Сергей-
Дата 3.3.2016, 07:35 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Бывалый
*


Профиль
Группа: Участник
Сообщений: 224
Регистрация: 2.8.2003
Где: Россия

Репутация: нет
Всего: 1



Всем доброго дня! Вопрос в сабже.  Пробовал на Delphi 7, XE5, XE10.  В чем может быть проблема?
Или Synchronize не предназначен для использования в консоли?

Код

program Project1;

{$APPTYPE CONSOLE}

uses
  Winapi.Windows,
  System.SysUtils,
  System.Classes;

type
  TTestTrd = class(TThread)
  protected
    msg: String;
    procedure Execute; override;
    procedure WriteToConsole;
  end;

  TTestClass = class(TObject)
  public
    procedure UpdateCons(S: String);
    procedure ShowMessageBox(S: string);
  end;

var
  TestClass: TTestClass;
  arr_thrd : array [0..9] of TTestTrd;
  I: integer;

{ TTestClass }


procedure TTestClass.ShowMessageBox(S: string);
begin
  MessageBox(0,PcHar(S),'',0);
end;

procedure TTestClass.UpdateCons(S: String);
begin
  WriteLn(S);
end;

{ TTestTrd }

procedure TTestTrd.Execute;
begin
  NameThreadForDebugging('TestTrd');
  msg := IntToStr(Handle);
  Synchronize(WriteToConsole);
end;

procedure TTestTrd.WriteToConsole;
begin
  TestClass.UpdateCons(msg); // тут ставлю брекпойнт, и он не срабатывает
end;

begin
  TestClass := TTestClass.Create;
  for I := Low(arr_thrd) to High(arr_thrd) do
  begin
    arr_thrd[I] := TTestTrd.Create(True);
    arr_thrd[I].Priority:=tpLower;
    arr_thrd[I].FreeOnTerminate:=True;
    arr_thrd[I].Resume;
  end;
  ExitThread(0);
end.


Это сообщение отредактировал(а) -Сергей- - 3.3.2016, 07:35
--------------------
Для утвердительного ответа достаточно лишь одного слова - "да". Все прочие слова придуманы, чтобы сказать "нет".
PM MAIL WWW ICQ MSN   Вверх
Doga
Дата 3.3.2016, 15:06 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Шустрый
*


Профиль
Группа: Участник
Сообщений: 115
Регистрация: 20.12.2007
Где: Россия, Обнинск

Репутация: нет
Всего: нет



Привет.

С каким значением аргумента CreateSuspended создаётся поток? 
Execute хотя бы вызывается?

А вообще, некоторое время назад, для вызова методов основного потока, 
у TThread появилась специальная версия Synchronize -StaticSynchronize
Однако в последних Rad Studio она уже успела устареть, т.к. обычная Synchronize 
сама стала статической (в XE8 - точно). 
Т.е. выбор корректного метода зависит от Вашего IDE.

PM MAIL WWW   Вверх
-Сергей-
Дата 3.3.2016, 15:54 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Бывалый
*


Профиль
Группа: Участник
Сообщений: 224
Регистрация: 2.8.2003
Где: Россия

Репутация: нет
Всего: 1



Doga, я же пример кода привел, там все ответы есть.
Код

arr_thrd[I] := TTestTrd.Create(True); 

значит CreateSuspended = True
Execute вызывается.

Провел небольшое исследование и выяснил, что Execute висит на первом же попавшемся Synchronize. И дальше не выполняется.
Можно изменить метод Execute и поставить бряк, например:
Код

procedure TTestTrd.Execute;
var
  i:integer;
begin
  NameThreadForDebugging('TestTrd');
  msg := IntToStr(Handle);
  Synchronize(WriteToConsole);
  i:=1;  // breakepoint
end;


Прошелся отладчиком по модулям, и дошел в SysUtils до этого метода (Delphi XE10):
Код

function WaitForSyncWaitObj(P: Pointer; Timeout: Cardinal): Integer;
begin
  Result := WaitForSingleObject(THandle(P), Timeout);
end;

Что означает, Synchronize ждет какого-то сигнала от основного потока. А он его и не дождется, поскольку Timeout = INFINITE, а основной поток я завершил ExitThread(0); (если не завершить, то RTL вызовет ExitProcess)


Это сообщение отредактировал(а) -Сергей- - 3.3.2016, 16:10
--------------------
Для утвердительного ответа достаточно лишь одного слова - "да". Все прочие слова придуманы, чтобы сказать "нет".
PM MAIL WWW ICQ MSN   Вверх
Doga
Дата 3.3.2016, 17:52 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Шустрый
*


Профиль
Группа: Участник
Сообщений: 115
Регистрация: 20.12.2007
Где: Россия, Обнинск

Репутация: нет
Всего: нет



Есть подозрение, что некоторые из Ваших 10 потоков пытаюся получить одновременный доступ к методу основного потока TTestClass.UpdateCons.

Для отладки, создайте только 1 поток, посмотрите как работает он один.

Возможно поможет StaticSynchronize, если она есть.
PM MAIL WWW   Вверх
-Сергей-
Дата 3.3.2016, 19:47 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Бывалый
*


Профиль
Группа: Участник
Сообщений: 224
Регистрация: 2.8.2003
Где: Россия

Репутация: нет
Всего: 1



Изначально у меня и был один.  И с одним потоком такая же беда.
А насчет StaticSynchronize:
[dcc32 Warning] Project1.dpr(37): W1000 Symbol 'StaticSynchronize' is deprecated: 'From C++ just use Synchronize now that it is just a static method'
Только причем тут  C++ ...

Это сообщение отредактировал(а) -Сергей- - 3.3.2016, 20:07
--------------------
Для утвердительного ответа достаточно лишь одного слова - "да". Все прочие слова придуманы, чтобы сказать "нет".
PM MAIL WWW ICQ MSN   Вверх
dnek
Дата 4.3.2016, 14:15 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Новичок



Профиль
Группа: Участник
Сообщений: 0
Регистрация: 1.4.2013

Репутация: нет
Всего: нет



В Вашем примере основной поток никогда не бывает свободным. Соответственно Synchronize никогда не сможет выполниться.

Этот ответ добавлен с нового Винграда - http://vingrad.com
PM MAIL   Вверх
-Сергей-
Дата 4.3.2016, 17:21 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Бывалый
*


Профиль
Группа: Участник
Сообщений: 224
Регистрация: 2.8.2003
Где: Россия

Репутация: нет
Всего: 1



dnek, если я не сделаю ExitThread(0), то приложение завершится, не дожидаясь завершения других потоков.
--------------------
Для утвердительного ответа достаточно лишь одного слова - "да". Все прочие слова придуманы, чтобы сказать "нет".
PM MAIL WWW ICQ MSN   Вверх
dnek
Дата 4.3.2016, 21:26 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Новичок



Профиль
Группа: Участник
Сообщений: 0
Регистрация: 1.4.2013

Репутация: нет
Всего: нет



Естественно, но и Synchronize после этого перестанет работать. Вам надо искать другой способ вызова WriteToConsole. Используйте Event, SimpleEvent, семафор, мютекс, наконец простой флаг в связке с InterlockedIncrement/InterlockedDecremen/InterlockedExchange - т.е.  какой-нибудь другой способ синхронизации потоков - и все у Вас будет ОК.

Этот ответ добавлен с нового Винграда - http://vingrad.com
PM MAIL   Вверх
kami
Дата 6.3.2016, 22:44 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Эксперт
***


Профиль
Группа: Завсегдатай
Сообщений: 1806
Регистрация: 25.8.2007
Где: Санкт-Петербург

Репутация: 23
Всего: 72



Synchronize можно спокойно использовать в консольном приложении, если понимать, что этот метод использует Event-ы. И основной поток должен проверять их состояние.
Видоизменим код так:

Код

type
  TTestTrd = class(TThread)
...
  public
    procedure BeforeDestruction; override;
  end;

var
  ThreadCount: integer = 0; // счетчик, сколько у нас еще работает потоков
{ TTestTrd }
procedure TTestTrd.BeforeDestruction;
begin
  inherited;
  Dec(ThreadCount); // когда поток уничтожается - уменьшаем счетчик.
end;

........

begin
  TestClass := TTestClass.Create;
  for I := Low(arr_thrd) to High(arr_thrd) do
  begin
    arr_thrd[I] := TTestTrd.Create(True);
    arr_thrd[I].Priority:=tpLower;
    arr_thrd[I].FreeOnTerminate:=True;
    arr_thrd[I].Start;
    inc(ThreadCount); // после создания очередного потока - увеличиваем счетчик.
   // понятно, что тут лучше было бы использовать InterlockedIncrement (а в BeforeDestruction - InterlockedDecrement)
  end;
  while ThreadCount>0 do // но вот что из Interlocked использовать здесь - увы, не представляю...
    CheckSynchronize(100); // даем возможность потокам вызвать Synchronize.
  readln; // это просто для паузы
end.

PM MAIL WWW   Вверх
dnek
Дата 10.3.2016, 18:27 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Новичок



Профиль
Группа: Участник
Сообщений: 0
Регистрация: 1.4.2013

Репутация: нет
Всего: нет



Цитата

  понятно, что тут лучше было бы использовать InterlockedIncrement (а в BeforeDestruction - InterlockedDecremen
   

Не "лучше было бы" а однозначно Interlocked~ или Atomic~

Цитата

   while ThreadCount>0 do // но вот что из Interlocked использовать здесь - увы, не представляю...
   

InterlockedCompareExchange или AtomicCmpExchange

Этот ответ добавлен с нового Винграда - http://vingrad.com
PM MAIL   Вверх
kami
Дата 11.3.2016, 17:43 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Эксперт
***


Профиль
Группа: Завсегдатай
Сообщений: 1806
Регистрация: 25.8.2007
Где: Санкт-Петербург

Репутация: 23
Всего: 72



Цитата(dnek @  10.3.2016,  18:27 Найти цитируемый пост)
InterlockedCompareExchange или AtomicCmpExchange

Про наличие этих функций я знаю. Но как применить их в контексте вышеприведенного кода?
Цитата(dnek @  10.3.2016,  18:27 Найти цитируемый пост)
Не "лучше было бы" а однозначно Interlocked~ или Atomic~

Не использовал их потому что весь эффект будет нивелирован в while.

Было бы очень хорошо, если бы вы показали использование InterlockedCompareExchange в этом коде.
PM MAIL WWW   Вверх
dnek
Дата 11.3.2016, 18:07 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Новичок



Профиль
Группа: Участник
Сообщений: 0
Регистрация: 1.4.2013

Репутация: нет
Всего: нет



Цитата

   Было бы очень хорошо, если бы вы показали использование InterlockedCompareExchange в этом коде.
   


Вместо
Код

while ThreadCount>0 do

использовать
Код

while AtomicCmpExchange(ThreadCount, ThreadCount, 0) > 0 do



Этот ответ добавлен с нового Винграда - http://vingrad.com
PM MAIL   Вверх
  
Ответ в темуСоздание новой темы Создание опроса
Правила форума "Delphi: Общие вопросы"
SnowyMetalFan
bemsPoseidon
Rrader

Запрещается!

1. Публиковать ссылки на вскрытые компоненты

2. Обсуждать взлом компонентов и делиться вскрытыми компонентами

  • Литературу по Дельфи обсуждаем здесь
  • Действия модераторов можно обсудить здесь
  • С просьбами о написании курсовой, реферата и т.п. обращаться сюда
  • Вопросы по реализации алгоритмов рассматриваются здесь
  • 90% ответов на свои вопросы можно найти в DRKB (Delphi Russian Knowledge Base) - крупнейшем в рунете сборнике материалов по Дельфи


Если Вам понравилась атмосфера форума, заходите к нам чаще! С уважением, Snowy, MetalFan, bems, Poseidon, Rrader.

 
1 Пользователей читают эту тему (1 Гостей и 0 Скрытых Пользователей)
0 Пользователей:
« Предыдущая тема | Delphi: Общие вопросы | Следующая тема »


 




[ Время генерации скрипта: 0.0814 ]   [ Использовано запросов: 21 ]   [ GZIP включён ]


Реклама на сайте     Информационное спонсорство

 
По вопросам размещения рекламы пишите на vladimir(sobaka)vingrad.ru
Отказ от ответственности     Powered by Invision Power Board(R) 1.3 © 2003  IPS, Inc.