Форум по Delphi программированию

Delphi Sources



Вернуться   Форум по Delphi программированию > Все о Delphi > [ "Начинающим" ]
Ник
Пароль
Регистрация <<         Правила форума         >> FAQ Пользователи Календарь Поиск Сообщения за сегодня Все разделы прочитаны

Ответ
 
Опции темы Поиск в этой теме Опции просмотра
  #1  
Старый 04.09.2014, 16:22
delphi_begin delphi_begin вне форума
Прохожий
 
Регистрация: 23.09.2011
Сообщения: 22
Репутация: 10
По умолчанию Два параллельных потока

Приветствую, господа!

Стоит такая задача: Записать содержимое таблицы в две сторонние БД.
Эту задачу необходимо выполнять параллельно - запись в каждую БД в отдельном потоке. Каждый из потоков использует разные компоненты доступа, чтобы не мешать друг другу.

Я написал код, который работает, однако как только запускается второй поток, первый становится на паузу и ждет, пока закончится второй. Мне же нужно, чтобы они отработали одновременно.
[Класс потока]
Код:
 Tload = class(TThread)
      IBDB:TIBDataBase; 
      search:TIBQuery;
      tsearch,treport:TIBTransaction;
      import_pre:TIBDataset;
      import_delete,pre_delete:TIBSQL;
      memo:Tmemo; 
   public
    procedure Execute; override;
    procedure CreareSpec(db:string;memo:tmemo); //определяет в какую БД пишем, и в какой компонент выводим логи
  
  end;
Процедура procedure CreareSpec(db:string;memo:tmemo);
//тут я динамически создаю компоненты, и их свойста для объекта потока
Код:
self.memo:=memo;
IBDB:=tibdatabase.Create(form1);
ibDB.DatabaseName:=db;
и т.д.
Процедура Execute
Код:
 procedure Tload.Execute;
var f:textfile;
begin
   inherited;
assignfile(f,'c:\'+memo.Name+'.txt');
rewrite(f);
memo.Clear;
try
тут я открываю набор данных из одной базы и вставляю их в другую базу циклом while not eof
каждая операция в цикле записывается в текстовый файл
каждая пятитысячная операция (i mod 5000=0) выводится в соотвествующий memo. У каждого объекта потока он точно будет разный.
в конце terminate

В коде программы
объявляю две переменные типа TLoad
A1,A2:Tload;

и вешаю на две кнопки запуск двух процессов
первая кнопка
Код:
if ibdb.Connected=false then ibdb.Open;
A1:=Tload.Create(true);
A1.Priority:=tpNormal;
A1.FreeOnTerminate:=true;
A1.CreareSpec(db_path1,memo3);
A1.Execute;
и вторая кнопка
Код:
if ibdb.Connected=false then ibdb.Open;
A2:=Tload.Create(true);
A2.Priority:=tpNormal;
A2.FreeOnTerminate:=true;
A2.CreareSpec(db_path2,memo3);
A2.Execute;

Как я уже говорил, как только я запускаю второй поток, первый становится на паузу. Я почитал литературу, но так и не нашел ответа. Буду рад Вашей помощи.

Админ: 2-х дневный бан за несоблюдение правил форума по оформлению кода.

Последний раз редактировалось Admin, 04.09.2014 в 19:24.
Ответить с цитированием
  #2  
Старый 08.09.2014, 13:38
Heneken Heneken вне форума
Новичок
 
Регистрация: 11.09.2011
Сообщения: 73
Версия Delphi: Delphi XE6
Репутация: 10
По умолчанию

Он именно ожидает? Или вылетает? Если ожидает,то возможно критическая секция

Последний раз редактировалось Heneken, 08.09.2014 в 13:42.
Ответить с цитированием
  #3  
Старый 08.09.2014, 13:52
Аватар для min@y™
min@y™ min@y™ вне форума
Заблокирован
 
Регистрация: 29.08.2014
Адрес: Рязань
Сообщения: 26
Версия Delphi: D7, CB6, etc
Репутация: 10
По умолчанию

А почему я тут не вижу ни одного вызова метода Synchronize()?
Ответить с цитированием
  #4  
Старый 08.09.2014, 14:55
Heneken Heneken вне форума
Новичок
 
Регистрация: 11.09.2011
Сообщения: 73
Версия Delphi: Delphi XE6
Репутация: 10
По умолчанию

Цитата:
Сообщение от min@y™
А почему я тут не вижу ни одного вызова метода Synchronize()?
Может и синхронизировать нечего..я как понял все в потоке делается
Ответить с цитированием
  #5  
Старый 08.09.2014, 16:40
icWasya icWasya вне форума
Местный
 
Регистрация: 09.11.2010
Сообщения: 499
Репутация: 10
По умолчанию

только надо не
Код:
A1.Execute;
а
Код:
A1.Resume;
Ответить с цитированием
  #6  
Старый 08.09.2014, 16:55
Аватар для min@y™
min@y™ min@y™ вне форума
Заблокирован
 
Регистрация: 29.08.2014
Адрес: Рязань
Сообщения: 26
Версия Delphi: D7, CB6, etc
Репутация: 10
По умолчанию Это чо такое было?

Цитата:
Сообщение от Heneken
Может и синхронизировать нечего..я как понял все в потоке делается
Ты прикалываешься, да? Даже боюсь предположить, что ты это серьёзно.
Там же обращения к VCL-объектам прямо в Execute()!

Маленький копипаст-ликбез из умной книжки:

Цитата:
Метод Synchronize()
В классе TThread определен метод Synchronize(), который позволяет вызывать некоторые из методов этого класса прямо из основного потока приложения. Определение метода Synchronize() имеет следующий вид:
Код:
procedure Synchronize(Method: TThreadMethod);
Параметр Method имеет тип TThreadMethod (означающий процедурный метод, не использующий никаких параметров), который определяется следующим образом:
Код:
type TThreadMethod = procedure of object;
Метод, передаваемый в качестве параметра Method, и является как раз тем методом, который затем выполняется из основного потока приложения. Возвращаясь к примеру с классом TTestThread, предположим, что мы хотим отобразить результат вычислений в строке редактирования на главной форме. Это можно сделать путем ввода в класс TTestThread метода, который вносит необходимые изменения в свойство Text строки редактирования, и последующего вызова этого метода с помощью процедуры Synchronize().

Предположим, этот метод называется GiveAnswer(). В листинге 11.1 представлен полный исходный Оод модуля ThrdU, который включает программную реализацию процесса обновления упомянутой выше строки редактирования на главной форме.

Листинг 11.1. Модуль ThrdU.PAS
Код:
unit ThrdU; 
 
interface
 
uses Classes;
 
type
  TTestThread = class(TThread) 
                private
                Answer: integer; 
               protected
                 procedure GiveAnswer;
                procedure Execute; override; 
              end;
 
implementation 
 
uses 
  SysUtils, Main; 
 
{ TTestThread }
 
procedure TTestThread.GiveAnswer; 
begin
  MainForm.Editl.Text := InttoStr(Answer); 
end;
 
procedure TTestThread.Execute; 
var
  I: Integer; begin
  FreeOnTerminate := True; 
  for I := 1 to 2000000 do begin
    if Terminated then Break; 
    Inc(Answer, Round(Abs(Sin(Sqrt(I))))); 
    Synchronize(GiveAnswer); 
  end; 
end;
 
end.
Мы уже знаем, что с помощью метода Synchronize() можно выполнять методы в контексте основного потока, но до сих пор мы обращались с ним как с таинственным черным ящиком. Мы знали, что он делает, но не знали как. Настало время приоткрыть завесу этой тайны.

При первом создании вторичного (или дополнительного) потока в приложении библиотека VCL создает и далее поддерживает скрытое окно потока в контексте своего основного потока. Единственная цель этого окна состоит в организации последовательности вызовов процедур, выполненных посредством метода Synchronize().

Метод Synchronize() сохраняет метод, заданный параметром Method, в закрытом поле FMethod и посылает определенное библиотекой VCL сообщение CM_EXECPROC в окно потока, передавая в качестве параметра lParam этого сообщения значение Self (в этом случае Self указывает на объект TThread). Когда процедура окна потока получает сообщение CM EXECPROC, она вызывает метод, заданный в поле FMethod с помощью экземпляра объекта TThread, переданного параметром lParam. Напомним, что поскольку это окно было создано в контексте основного потока, процедура окна для него также выполняется основным потоком. Следовательно, метод, указанный в поле FMethod, также вызывается основным потоком.
Ответить с цитированием
  #7  
Старый 08.09.2014, 19:28
lmikle lmikle вне форума
Модератор
 
Регистрация: 17.04.2008
Сообщения: 8,098
Версия Delphi: 7, XE3, 10.2
Репутация: 49089
По умолчанию

Метод Synchronize нужен только тогда, когда происходит обращение к VCL (и не только к VCL) объектам, находящимся В ГЛАВНОМ ПОТОКЕ ПРИЛОЖЕНИЯ. В данном же случае все компоненты находятся в дополнительном потоке, так что с этим проблем быть не должно.

Я бы грешил на какие-нить объекты синхронизации внутри самих компонентов доступа к БД. Но в таком случае тормозился бы второй поток, т.к. первый уже их занял.

Так что тут, видимо, действительно дело в прямом вызове метода Execute, который, вообще-то, должен быть в секции protected, но ТСом перенесен в секцию public, что и позволило вызвать этот метод напрямую в основном потоке приложения, а не создавая дополнительный поток.

ТС, поменяй вызов Execute на выов Resume и наступит тебе счастье
Ответить с цитированием
  #8  
Старый 08.09.2014, 19:49
Аватар для min@y™
min@y™ min@y™ вне форума
Заблокирован
 
Регистрация: 29.08.2014
Адрес: Рязань
Сообщения: 26
Версия Delphi: D7, CB6, etc
Репутация: 10
По умолчанию

Цитата:
Метод Synchronize нужен только тогда, когда происходит обращение к VCL (и не только к VCL) объектам, находящимся В ГЛАВНОМ ПОТОКЕ ПРИЛОЖЕНИЯ. В данном же случае все компоненты находятся в дополнительном потоке, так что с этим проблем быть не должно.
Рукалицо! В каком потоке живёт этот ОКОННЫЙ объект, как ты думаешь?
Ответить с цитированием
Ответ


Delphi Sources

Опции темы Поиск в этой теме
Поиск в этой теме:

Расширенный поиск
Опции просмотра

Ваши права в разделе
Вы не можете создавать темы
Вы не можете отвечать на сообщения
Вы не можете прикреплять файлы
Вы не можете редактировать сообщения

BB-коды Вкл.
Смайлы Вкл.
[IMG] код Вкл.
HTML код Выкл.
Быстрый переход


Часовой пояс GMT +3, время: 14:28.


 

Сайт

Форум

FAQ

Соглашения

Прочее

 

Copyright © Форум "Delphi Sources" by BrokenByte Software, 2004-2025