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

Поиск:

Ответ в темуСоздание новой темы Создание опроса
> поток запущен, а форма висит 
V
    Опции темы
chikistbuch
Дата 28.6.2012, 22:05 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Шустрый
*


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

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



Всем привет.

Пишу все в unit1.
Код

...
type
   TPotok = class(TThread)
    private
      filename: string;
      procedure loaddata;
     { Private declarations }
    protected
      procedure Execute; override;
end;

var
    potok: TPotok;


Код

procedure TPotok.Execute;
begin
   Synchronize(loaddata); // Вызов метода с синхронизацией
end;

procedure TForm1.ToolButton7Click(Sender: TObject);
begin
  form1.OpenDialog1.Filter:='Файлы Excel|*.xls; *.xlsx';
  if form1.OpenDialog1.Execute() then begin
    potok := TPotok.Create(true);// true - после создания класса поток автоматически запущен не будет
    potok.FreeOnTerminate := true;//после завершения кода потока он сразу завершится
    potok.filename := form1.Opendialog1.FileName;
    potok.Priority := tpNormal;//Устанавливаем приоритет
    potok.Resume;//Запускаем поток
  end;
end;


Процедура loaddata запускается и выполняется, а вот форма в это время висит. 
про потоки читал здесь: http://callipso.bestcode.org/delphi/artical/num2.html

PM MAIL   Вверх
Чучмек
Дата 28.6.2012, 22:15 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


НЭТ БИЛЭТ
**


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

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



loaddata с формой взаимодействует?
Наверняка, иначе зачем тогда Synchronize?
Вот Synchronize и блокирует основной поток, наверно.


--------------------
умную мысль держи при себе, а дурной - поделись с другими 
PM MAIL   Вверх
chikistbuch
Дата 28.6.2012, 22:54 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Шустрый
*


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

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



Код

procedure TPotok.loaddata;
var
  WorkBook, Sheet: Variant;
  i, j, kolKolonok, kolStrok:integer;
  sql, sql_1: string;
  maxID: array [1..2] of string;
  sqlArray: OLEVariant;
  bool:boolean;
begin

  try
    Excel := CreateOleObject('Excel.Application');//создаем что-то типа excel
  except
    MessageBox(Application.ActiveFormHandle, 'MS Excel не найден!'+#13#10+'Для работы программы необходимо установить MS Excel.', 'Внимание!', MB_ICONWARNING or MB_OK);
    exit;
  end;

  Excel.Application.EnableEvents := false;// Отключаем реакцию Excel на события, чтобы ускорить вывод информации
  Excel.DisplayAlerts:=False;//отключаем сообщения excel'я

  WorkBook := Excel.WorkBooks.Open(filename);//открываем файл
  PostMessage(form1.Handle, WM_CloseExcel, 0, 0);//закрываем excel после выполнения данной процедуры

  try
    Sheet := Workbook.Sheets.Item[1] //выбираем лист
  except
    MessageBox(Application.ActiveFormHandle, 'Ошибка!'+#13#10+'Файл MS Excel пуст или поврежден.', 'Внимание!', MB_ICONWARNING or MB_OK);
    exit;
  end;

  kolStrok:=Sheet.UsedRange.Rows.Count;
  kolKolonok:=Sheet.UsedRange.Columns.Count;
  sqlArray:=Sheet.UsedRange.Value; //прочитали все значения в массив

  StatusProgressBar.Position:=0;
  StatusProgressBar.Visible:=true;
  StatusProgressBar.Max:=kolStrok;

  for i := 1 to kolKolonok do begin //проверяем правильность названия колонок
    j:=0;
    bool:=false;//индикатор совпадения имени

    while (j<form4.CheckListBox1.Items.Count-1) AND (NOT bool) do begin
      if AnsiUpperCase(sqlArray[1,i])=AnsiUpperCase(form4.CheckListBox1.Items.Strings[j]) then begin //если название колонки совпадает с названием колонки в БД
        sqlArray[1,i]:=form1.getAS(sqlArray[1,i], 2);//записали название колонки familia
        bool:=true;
      end;
      j:=j+1;
    end;

    if not bool then begin //если совпадений в названии колонки не найдено
      MessageBox(Application.ActiveFormHandle, pChar('Ошибка! Неверное название '+inttostr(i)+' колонки: "'+string(sqlArray[1,i])+'".'), 'Внимание!', MB_ICONWARNING or MB_OK);
      exit;//прерываем выполнение кода
    end;
  end;

  if  MessageBox(Application.ActiveFormHandle, 'Загрузить данные из указанного файла?', 'Внимание!', MB_ICONWARNING or MB_YESNO) = IDNO then exit;//прерываем выполнение кода

  form1.UniQuery2.SQL.Text:='SELECT MAX(`id`) FROM spisok';//узнали макс id
  form1.UniQuery2.Execute;
  maxID[1]:=form1.UniQuery2.Fields.Fields[0].AsString;

  sql:='PREPARE excelInsert FROM "INSERT INTO `spisok` ('; //подготавливаем sql запрос на ввод данных

  for i:=1 to kolKolonok do begin
    sql:=sql+'`'+sqlArray[1,i]+'`, ';
    sql_1:=sql_1+'@'+sqlArray[1,i]+', ';//для EXECUTE
  end;
  delete(sql, length(sql)-1, 2);
  delete(sql_1, length(sql_1)-1, 2);//для EXECUTE
  sql:=sql+') VALUES (';

  for i:=1 to kolKolonok do begin
    sql:=sql+'?, ';
  end;
  delete(sql, length(sql)-1, 2);
  sql:=sql+')";';           //подготовили запрос на вставку

  for i := 2 to kolStrok do begin //так как первая строка содержит названия колонок
    if i mod 10 = 0 then StatusProgressBar.Position:=i;
    for j := 1 to kolKolonok do begin
      if string(sqlArray[i,j])='' then sql:=sql+'SET @'+string(sqlArray[1,j])+' = NULL;'//проверяем не пуста ли строка
        else sql:=sql+'SET @'+string(sqlArray[1,j])+' = "'+string(sqlArray[i,j])+'";';//формируем значения
    end;
  sql:=sql+'EXECUTE excelInsert USING '+sql_1+';';;
  end;

  StatusProgressBar.Position:=kolStrok;

  form1.UniQuery2.SQL.Text:=sql;
  form1.UniQuery2.Execute; //вставили все значения

  form1.UniQuery2.SQL.Text:='SELECT MAX(`id`) FROM spisok';//узнали макс id
  form1.UniQuery2.Execute;
  maxID[2]:=form1.UniQuery2.Fields.Fields[0].AsString;

  if maxID[1]='' then sql_1:='WHERE id < '+maxID[2] //условие запроса
    else sql_1:='WHERE id BETWEEN '+maxID[1]+' AND '+maxID[2];
  sql:='UPDATE spisok SET data_redaktirovania = "'+FormatDateTime('yyyy:mm:dd',Now())+'" '+sql_1;
  form1.UniQuery2.SQL.Text:=sql;
  form1.UniQuery2.Execute;

 А как сделать чтобы не блокировала?
Пускай sql сформирую в потоке

Код

procedure TPotok.createSQL;
var
  i, j, kolKolonok, kolStrok:integer;
  sql, sql_1: string;
  sqlArray: OLEVariant;
begin
  sql:='PREPARE excelInsert FROM "INSERT INTO `spisok` ('; //подготавливаем sql запрос на ввод данных

  for i:=1 to kolKolonok do begin
    sql:=sql+'`'+sqlArray[1,i]+'`, ';
    sql_1:=sql_1+'@'+sqlArray[1,i]+', ';//для EXECUTE
  end;
  delete(sql, length(sql)-1, 2);
  delete(sql_1, length(sql_1)-1, 2);//для EXECUTE
  sql:=sql+') VALUES (';

  for i:=1 to kolKolonok do begin
    sql:=sql+'?, ';
  end;
  delete(sql, length(sql)-1, 2);
  sql:=sql+')";';           //подготовили запрос на вставку

  for i := 2 to kolStrok do begin //так как первая строка содержит названия колонок
    if i mod 10 = 0 then StatusProgressBar.Position:=i;
    for j := 1 to kolKolonok do begin
      if string(sqlArray[i,j])='' then sql:=sql+'SET @'+string(sqlArray[1,j])+' = NULL;'//проверяем не пуста ли строка
        else sql:=sql+'SET @'+string(sqlArray[1,j])+' = "'+string(sqlArray[i,j])+'";';//формируем значения
    end;
  sql:=sql+'EXECUTE excelInsert USING '+sql_1+';';;
  end;

  StatusProgressBar.Position:=kolStrok;
end;

а как обратно передать значение sql в loaddata и дождаться выполнение TPotok.createSQL, а то пишет что SQL пуст
PM MAIL   Вверх
ZBugz
Дата 29.6.2012, 08:18 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Опытный
**


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

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



Попробуй повтыкать Application.ProcessMessages();
PM MAIL   Вверх
Чучмек
Дата 29.6.2012, 09:55 (ссылка) |    (голосов:1) Загрузка ... Загрузка ... Быстрая цитата Цитата


НЭТ БИЛЭТ
**


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

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



Посмотри в чем разница
Код

type tmt1=class(tthread)
 procedure m;
 procedure execute;override;
end;


{ tmt1 }
procedure tmt1.execute;
begin
  inherited;
  Synchronize(m);
end;

procedure tmt1.m;
var
 i:integer;
begin
for i:=0 to 99 do
 begin
 form1.Caption:=inttostr(i);
 sleep(100);
 end;
end;



Код

type tmt2=class(tthread )
 s:string;
 procedure m;
 procedure execute;override;
end;

{ tmt2 }

procedure tmt2.execute;
var
 i:integer;
begin
  inherited;
for i:=0 to 99 do
 begin
 s:=inttostr(i);
 Synchronize(m);
 sleep(100);
 end;
end;

procedure tmt2.m;
begin
form1.Caption:=s;
end;





--------------------
умную мысль держи при себе, а дурной - поделись с другими 
PM MAIL   Вверх
MetalFan
Дата 29.6.2012, 14:00 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Аццкий Сотона
****


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

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



Цитата(Чучмек @  29.6.2012,  09:55 Найти цитируемый пост)
Посмотри в чем разница

Верно подметил.

Использовать поток только для того, чтобы в нем сразу вызвать Synchronize - бессмысленно.


--------------------
There are always someone smarter than you...
PM MAIL   Вверх
northener
Дата 29.6.2012, 14:09 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Эксперт
***


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

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



Цитата(Чучмек @  28.6.2012,  22:15 Найти цитируемый пост)
Вот Synchronize и блокирует основной поток, наверно. 

Синхронайз ничего не блокирует. Но все что выполняется внутри Synchronize выполняется в основном потоке.


--------------------
Но только лошади летают вдохновенно.
Иначе лошади разбились бы мгновенно!
PM MAIL   Вверх
MetalFan
Дата 29.6.2012, 16:49 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Аццкий Сотона
****


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

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



Цитата(northener @  29.6.2012,  14:09 Найти цитируемый пост)
Синхронайз ничего не блокирует.

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


Это сообщение отредактировал(а) MetalFan - 29.6.2012, 16:49


--------------------
There are always someone smarter than you...
PM MAIL   Вверх
northener
Дата 29.6.2012, 17:09 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Эксперт
***


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

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



Цитата(MetalFan @  29.6.2012,  16:49 Найти цитируемый пост)
Ну здрасти?!

Ну собственно я отвечал на 
Цитата(Чучмек @  28.6.2012,  22:15 Найти цитируемый пост)
Вот Synchronize и блокирует основной поток, наверно. 




--------------------
Но только лошади летают вдохновенно.
Иначе лошади разбились бы мгновенно!
PM MAIL   Вверх
northener
Дата 30.6.2012, 01:02 (ссылка)    | (голосов:1) Загрузка ... Загрузка ... Быстрая цитата Цитата


Эксперт
***


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

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



Ну и вдогонку.
Цитата(MetalFan @  29.6.2012,  16:49 Найти цитируемый пост)
Блокируется поток, вызвавший Synchronize

Ну не "блокируется" этот поток! Он продолжает выполняться в соответствии со своим кодом. Но войдя в Synchronize код этого потока выполняется не в нём самом, а в основном потоке приложения.


--------------------
Но только лошади летают вдохновенно.
Иначе лошади разбились бы мгновенно!
PM MAIL   Вверх
XperT
Дата 30.6.2012, 13:39 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Опытный
**


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

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



Цитата(northener @ 30.6.2012,  01:02)
Ну и вдогонку.
Цитата(MetalFan @  29.6.2012,  16:49 Найти цитируемый пост)
Блокируется поток, вызвавший Synchronize

Ну не "блокируется" этот поток! Он продолжает выполняться в соответствии со своим кодом. Но войдя в Synchronize код этого потока выполняется не в нём самом, а в основном потоке приложения.

Как раз таки нет: поток переходит в состояние suspend, а управление передаётся основному потоку. Когда нужная функция отработает в основном потоке, вызывающий поток опять получает процессорное время и продолжает свою работу.
PM MAIL   Вверх
northener
Дата 1.7.2012, 00:46 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Эксперт
***


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

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



Цитата(MetalFan @  29.6.2012,  16:49 Найти цитируемый пост)
Ну здрасти?!

Цитата(XperT @  30.6.2012,  13:39 Найти цитируемый пост)
Как раз таки нет

Это уже похоже на спор о терминологии. Говорим одно и то же, но предпочитаем использовать разные термины. 
smile




--------------------
Но только лошади летают вдохновенно.
Иначе лошади разбились бы мгновенно!
PM MAIL   Вверх
XperT
Дата 1.7.2012, 10:06 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Опытный
**


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

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



Говорим совсем о разном. Попробую объяснить по другому:
При вызове Synchronize, вызывающий поток переходит в состояние suspend, т.е. ему перестает выделятся процессорное время, т.е. он блокируется. 
По вашем описанию похоже, что вы думаете, что на момент выполнения Synchronize этот поток на время становится главным или что-то в этом роде, так как у меня нету предположений как он может не блокироваться и в этот же момент не выполнятся.


PM MAIL   Вверх
chikistbuch
Дата 1.7.2012, 13:05 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Шустрый
*


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

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



нихера не получается  smile 
PM MAIL   Вверх
Чучмек
Дата 1.7.2012, 14:23 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


НЭТ БИЛЭТ
**


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

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



1 Преременную Excel  в TPotok
2 Основную часть кода из loaddata в Execute 
3 Что такое StatusProgressBar?  ProgressBar на форме?
добавь в TPotok переменные 
   ProgressBar и UniQuery.
 до запуска потока выполни:
Код

potok.ProgressBar:=StatusProgressBar ;
potok.UniQuery:=form1.UniQuery2; 

Добавь в TPotok  также переменные:
   ProgressBarPosition
   ProgressBarVisible
   ProgressBarMax
Все обращения к
   form1.UniQuery2
  StatusProgressBar.Position
  StatusProgressBar.Visible
  StatusProgressBar.Max 
 замени на обращения к
  UniQuery
   ProgressBarPosition
   ProgressBarVisible
   ProgressBarMax
с form4.CheckListBox1 - аналогично: В TPotok  переменную типа tstringlist, в которую, до запуска потока, копируешь содержимое form4.CheckListBox1.Items
в tpotok добавляешь процедуру
Код

procedure tpotok.XXX;
 begin
  StatusProgressBar.Position:=ProgressBarPosition;
  StatusProgressBar.Visible:=ProgressBarVisible;
  StatusProgressBar.Max:= ProgressBarMax;
 end;
  
Везде где нужно обновить вид StatusProgressBar  вызываешь  Synchronize(XXX);
4 MessageBox(Application.ActiveFormHandle,... замени, для начала, на MessageBox(0,...
5 Надеюсь UniQuery потокозащищенный компонент.
P.S. UniQuery  для каждого потока свой
P.P.S В TPotok  переопредели конструктор, в который будешь сразу передавать form1.Opendialog1.FileName;StatusProgressBar;form1.UniQuery2;form4.CheckListBox1.Items

Добавлено через 12 минут и 3 секунды
Цитата(chikistbuch @  28.6.2012,  22:54 Найти цитируемый пост)
form1.getAS
 этого тоже не должно быть в потоке.
 


Это сообщение отредактировал(а) Чучмек - 1.7.2012, 14:29


--------------------
умную мысль держи при себе, а дурной - поделись с другими 
PM MAIL   Вверх
Страницы: (3) Все [1] 2 3 
Ответ в темуСоздание новой темы Создание опроса
Правила форума "Delphi: Общие вопросы"
SnowyMetalFan
bemsPoseidon
Rrader

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

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

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

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


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

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


 




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


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

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