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

Поиск:

Ответ в темуСоздание новой темы Создание опроса
> Синхронизация потока, созданного при помощи createthread 
:(
    Опции темы
Sunvas
  Дата 13.12.2006, 23:42 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Соль и сахар
****


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

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



Вот есть простой нерабочий код:
Код

unit Unit1;

interface

uses
  Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms,
  Dialogs, StdCtrls;

type
  TForm1 = class(TForm)
    Button1: TButton;
    Button2: TButton;
    procedure Button2Click(Sender: TObject);
    procedure Button1Click(Sender: TObject);
  private
    { Private declarations }
  public
    { Public declarations }
  end;
  procedure thred;stdcall;
var
  Form1: TForm1;
  m:word;
implementation
var
potok,id:cardinal;

procedure thred;
begin
while true do
begin
sleep(200);
inc(m);
if m=10 then form1.Button2.Click;
end;
end;
{$R *.dfm}

procedure TForm1.Button2Click(Sender: TObject);
begin
showmessage('Закрываюсь!');
terminatethread(potok,0);
close;
end;

procedure TForm1.Button1Click(Sender: TObject);
begin
m:=0;
potok:=createthread(nil,128,@thred,nil,0,id);
end;

end.

В принципе причина неработоспособности ясна - нет синхронизации.
Я долго искал но не нашел ничего про синхронизацию потоков созданных при помощи createthread (без класса TThread).
Помогите сделать код, преведеный выше, рабочим. smile 


--------------------
Воспитывая детей по своему образу и подобию, родители почему-то надеются, что они будут лучше их.
PM MAIL   Вверх
Ibragim
Дата 14.12.2006, 00:12 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Бывалый
*


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

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



Вопрос не в синхронизации, а в вызове form1.Button2.Click; 
Такие финты с визуальными контролами глючат из-под потоков. Можно только SendMessage этому контролу. А так все нормально, нечего здесь синхронизировать IMHO - захотел и удалил smile 

PS Offtop О, сообщение юбилейное 100 smile 

Это сообщение отредактировал(а) Ibragim - 14.12.2006, 00:13
PM MAIL   Вверх
Snowy
Дата 14.12.2006, 00:22 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Эксперт
****


Профиль
Группа: Модератор
Сообщений: 11363
Регистрация: 13.10.2004
Где: Питер

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



Sunvas, ну уже пора знать про этот топ: http://forum.vingrad.ru/index.php?showtopic=60076
Что касается VCL. 
Да, нежелательно обращаться из стороннего потока, ибо VCL работает в основном.
Но, если защитить синхронизацией, то вполне допустимо.
PM MAIL   Вверх
Alexeis
Дата 14.12.2006, 00:42 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Амеба
Group Icon


Профиль
Группа: Админ
Сообщений: 11743
Регистрация: 12.10.2005
Где: Зеленоград

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



Sunvas, c VCL нормально синхронизирует только метод Sincronize потомков TThread. Большинство объектов имеют между собой внутренние связи, которые нельзя ограничить, т.е. всегда есть шанс обратиться одновременно из двух потоков к общей памяти.


--------------------
Vit вечная память.

Обсуждение действий администрации форума производятся только в этом форуме

гениальность идеи состоит в том, что ее невозможно придумать
PM ICQ Skype   Вверх
Snowy
Дата 14.12.2006, 01:13 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Эксперт
****


Профиль
Группа: Модератор
Сообщений: 11363
Регистрация: 13.10.2004
Где: Питер

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



alexeis1, ну это ты слишком загнул.
Синхронизацию можно установить всегда.
У VCL есть своя специфика. Но не до такой степени...
PM MAIL   Вверх
Sunvas
Дата 14.12.2006, 19:08 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Соль и сахар
****


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

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



Цитата(Snowy @  14.12.2006,  00:22 Найти цитируемый пост)
Sunvas, ну уже пора знать про этот топ: http://forum.vingrad.ru/index.php?showtopic=60076

Я знаю про этот топ. Однако просматривая его я не увидел, чтобы там поток создавался без класса tthread. Может я просто невнимательно читал.. smile 

Цитата(alexeis1 @  14.12.2006,  00:42 Найти цитируемый пост)
Sunvas, c VCL нормально синхронизирует только метод Sincronize потомков TThread.

Читаем тему внимательней:

Цитата(Sunvas @  13.12.2006,  23:42 Найти цитируемый пост)
без класса TThread

 smile 


--------------------
Воспитывая детей по своему образу и подобию, родители почему-то надеются, что они будут лучше их.
PM MAIL   Вверх
Alexeis
Дата 14.12.2006, 20:44 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Амеба
Group Icon


Профиль
Группа: Админ
Сообщений: 11743
Регистрация: 12.10.2005
Где: Зеленоград

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



Sunvas, я это понимаю, но ведь требуется именно синхронизация с VCL, я смотрел этот (Sincronize) и как я понял суть его в том, что в определенный момент (у VCL есть спец. мьютекс позволяющий корректно это делать) останавливается главный поток и второй поток становится за главного и выполняет все нужные операции, после чего он должен разблокировать исходный главный поток. Можно посмотреть как это там реализовано и сделать аналогично, но уже без Thread.

Добавлено @ 20:57 
Получается что главный поток большую часть времени владеет VCL мьютексом и в определенные моменты его отдает, второй поток должен ждать этого момента и его захватить.


--------------------
Vit вечная память.

Обсуждение действий администрации форума производятся только в этом форуме

гениальность идеи состоит в том, что ее невозможно придумать
PM ICQ Skype   Вверх
Alexeis
Дата 14.12.2006, 22:12 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Амеба
Group Icon


Профиль
Группа: Админ
Сообщений: 11743
Регистрация: 12.10.2005
Где: Зеленоград

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



Вот этот метод класса можно вызывать без того чтобы создавать сам класс и тем самым синхронизироваться с VCL. Не создавая потомка TThread.
Код

class procedure TThread.Synchronize(ASyncRec: PSynchronizeRecord);
var
  SyncProc: TSyncProc;
begin
  if GetCurrentThreadID = MainThreadID then
    ASyncRec.FMethod
  else
  begin
{$IFDEF MSWINDOWS}
    SyncProc.Signal := CreateEvent(nil, True, False, nil);
    try
{$ENDIF}
{$IFDEF LINUX}
      FillChar(SyncProc, SizeOf(SyncProc), 0);  // This also initializes the cond_var
{$ENDIF}
      EnterCriticalSection(ThreadLock);
      try
        if SyncList = nil then
          SyncList := TList.Create;
        SyncProc.SyncRec := ASyncRec;
        SyncList.Add(@SyncProc);
        SignalSyncEvent;
        if Assigned(WakeMainThread) then
          WakeMainThread(SyncProc.SyncRec.FThread);
{$IFDEF MSWINDOWS}
        LeaveCriticalSection(ThreadLock);
        try
          WaitForSingleObject(SyncProc.Signal, INFINITE);
        finally
          EnterCriticalSection(ThreadLock);
        end;
{$ENDIF}
{$IFDEF LINUX}
        pthread_cond_wait(SyncProc.Signal, ThreadLock);
{$ENDIF}
      finally
        LeaveCriticalSection(ThreadLock);
      end;
{$IFDEF MSWINDOWS}
    finally
      CloseHandle(SyncProc.Signal);
    end;
{$ENDIF}
    if Assigned(ASyncRec.FSynchronizeException) then raise ASyncRec.FSynchronizeException;
  end;
end;





--------------------
Vit вечная память.

Обсуждение действий администрации форума производятся только в этом форуме

гениальность идеи состоит в том, что ее невозможно придумать
PM ICQ Skype   Вверх
Sunvas
Дата 14.12.2006, 22:39 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Соль и сахар
****


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

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



Цитата(alexeis1 @  14.12.2006,  22:12 Найти цитируемый пост)
Вот этот метод класса можно вызывать без того чтобы создавать сам класс и тем самым синхронизироваться с VCL.

Че-то я не врубился как его вызывать... Туплю однако.


--------------------
Воспитывая детей по своему образу и подобию, родители почему-то надеются, что они будут лучше их.
PM MAIL   Вверх
Alexeis
Дата 14.12.2006, 23:05 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Амеба
Group Icon


Профиль
Группа: Админ
Сообщений: 11743
Регистрация: 12.10.2005
Где: Зеленоград

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



Код

TThread.Synchronize(peremennaea);


Так же как конструктор. Класс Объект еще не существует а конструктор можно вызывать.

Это сообщение отредактировал(а) alexeis1 - 14.12.2006, 23:06


--------------------
Vit вечная память.

Обсуждение действий администрации форума производятся только в этом форуме

гениальность идеи состоит в том, что ее невозможно придумать
PM ICQ Skype   Вверх
bems
Дата 14.12.2006, 23:08 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Эксперт
****


Профиль
Группа: Комодератор
Сообщений: 3400
Регистрация: 5.1.2006

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



Цитата(Snowy @  14.12.2006,  01:13 Найти цитируемый пост)
Синхронизацию можно установить всегда.
кроме тех случаев когда это уже как-то мутно сделано и есть шанс получить дедлок



--------------------
Обижено школьников: 8
PM MAIL   Вверх
Snowy
Дата 14.12.2006, 23:58 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Эксперт
****


Профиль
Группа: Модератор
Сообщений: 11363
Регистрация: 13.10.2004
Где: Питер

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



Да не так уж всё сложно.
Но в данном случае проще нарисовать, чем объяснить smile
Создаём критическую секцию.
В OnIdle отпускаем её, и сразу снова занимаем.
Таким образом мы подготовили Application к синхронизации.
Теперь нашь поток должен просто занять секцию. 
Если занял, то основной поток засыпает до тех пор, пока мы не отпустим секцию, и вся VCL работа выполняется уже в нём.
После этого отпускаем секцию и её снова получает основной, вместе с управлением.
Получается такая вот весёлая секция - кто ей владеет, тот и рулит VCL'ем.
Обычно ей владеет основной поток.
Но, если он ничем не занят, то рулилку при необходимости может взять второстепенный.
PM MAIL   Вверх
Sunvas
Дата 15.12.2006, 00:08 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Соль и сахар
****


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

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



Цитата(alexeis1 @  14.12.2006,  23:05 Найти цитируемый пост)
Так же как конструктор. Класс Объект еще не существует а конструктор можно вызывать.

Ну это я давно догадался. Просто не пойму почему Делфи упорно видит исключительно функцию
Код

class procedure TThread.Synchronize(AThread: TThread; AMethod: TThreadMethod);

И не хочет ни в какую видеть ту, что ты написал??


--------------------
Воспитывая детей по своему образу и подобию, родители почему-то надеются, что они будут лучше их.
PM MAIL   Вверх
Alexeis
Дата 15.12.2006, 00:59 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Амеба
Group Icon


Профиль
Группа: Админ
Сообщений: 11743
Регистрация: 12.10.2005
Где: Зеленоград

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



Цитата(Sunvas @  15.12.2006,  00:08 Найти цитируемый пост)
И не хочет ни в какую видеть ту, что ты написал?? 

А блин, она в привате smile
Ну тогда просто сделать процедуру и включить в нее этот код. Он делает по сути тоже, что Snowy сказал, вот только не зачем помещать критическую секцию в OnIdle, потому что одна такая секция, точнее мьютекс похоже уже включена в цикл обработки TApplication. Хорошо бы в этом разобраться. 


--------------------
Vit вечная память.

Обсуждение действий администрации форума производятся только в этом форуме

гениальность идеи состоит в том, что ее невозможно придумать
PM ICQ Skype   Вверх
Alexeis
Дата 15.12.2006, 01:29 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Амеба
Group Icon


Профиль
Группа: Админ
Сообщений: 11743
Регистрация: 12.10.2005
Где: Зеленоград

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



так и есть. Следующий фрагмент взят из функции обработки сообщений класса TApplication

Код

...............
        WM_THEMECHANGED:
          if ThemeServices.ThemesEnabled then
            ThemeServices.ApplyThemeChange;
        WM_NULL:
          CheckSynchronize;
      else
        Default;
.............

CheckSynchronize; - позволяет блокироваться главному потоку.

Вот что про нее сказано в модуле classes
Цитата

{  Call CheckSynchronize periodically within the main thread in order for
   background threads to synchronize execution with the main thread.  This
   is mainly for applications that have an event driven UI such as Windows
   or XWindows (Qt/CLX).  The best place this can be called is during Idle
   processing.  This guarantees that the main thread is in a known "good"
   state so that method calls can be safely made.  Returns True if a method
   was synchronized.  Returns False if there was nothing done.
}


А вот ее фрагмент 
Код

function CheckSynchronize(Timeout: Integer = 0): Boolean;
var
  SyncProc: PSyncProc;
  LocalSyncList: TList;
begin
  if GetCurrentThreadID <> MainThreadID then
    raise EThread.CreateResFmt(@SCheckSynchronizeError, [GetCurrentThreadID]);
  if Timeout > 0 then
    WaitForSyncEvent(Timeout)
  else
    ResetSyncEvent;
  LocalSyncList := nil;
  EnterCriticalSection(ThreadLock);
......................


Т.е. как видно  она зависима от глобальной критической секции ThreadLock

Если она занята, то главный поток тут заблокируется.

Если вернуться к коду class procedure TThread.Synchronize(ASyncRec: PSynchronizeRecord);

Код

....................
   EnterCriticalSection(ThreadLock);
      try
        if SyncList = nil then
          SyncList := TList.Create;
        SyncProc.SyncRec := ASyncRec;
        SyncList.Add(@SyncProc);
        SignalSyncEvent;
        if Assigned(WakeMainThread) then
          WakeMainThread(SyncProc.SyncRec.FThread);
{$IFDEF MSWINDOWS}
        LeaveCriticalSection(ThreadLock);
        try
          WaitForSingleObject(SyncProc.Signal, INFINITE);
        finally
          EnterCriticalSection(ThreadLock);
        end;
......................


То видно, что оба метода используют одну и ту же критическую секцию и могут ее занимать только по очереди. Значит нужно просто дождаться пока она освободиться и затем сразу ее занять. После того как мы ее заняли, то правда нужно будет еще дождаться пока на ней заблокируется основной поток иначе за промежуток времени между тем как второй поток уже занял критическую секцию, а основной поток не вернулся опять и не заблокировался работают одновременно 2 потока паралелльно.


--------------------
Vit вечная память.

Обсуждение действий администрации форума производятся только в этом форуме

гениальность идеи состоит в том, что ее невозможно придумать
PM ICQ Skype   Вверх
Ответ в темуСоздание новой темы Создание опроса
Правила форума "Delphi: Общие вопросы"
SnowyMetalFan
bemsPoseidon
Rrader

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

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

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

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


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

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


 




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


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

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