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

Delphi Sources



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

Ответ
 
Опции темы Поиск в этой теме Опции просмотра
  #1  
Старый 04.01.2008, 23:12
~ SaM ~ ~ SaM ~ вне форума
Начинающий
 
Регистрация: 05.01.2007
Адрес: Днепропетровск
Сообщения: 141
Репутация: 25
По умолчанию Одновременное выполнение процедур/функций

Столкнулся я с задачей, когда времени на ее решение (программного) нет! Суть такова : Есть около 20-30 процедур, которые перебирают уйму информации. На все это уходит много времени, ибо данных много(очень много)!

Возможно ли выполнять несколько процедур одновременно???
Ответить с цитированием
  #2  
Старый 05.01.2008, 15:39
Аватар для The Shadow
The Shadow The Shadow вне форума
Продвинутый
 
Регистрация: 11.06.2007
Адрес: Уфа, Россия
Сообщения: 793
Репутация: 35
По умолчанию

Потоки не подходят?
__________________
Что делать, когда сломался комп:
1. Если вы юзер - делать ноги.
2. Если ремонтник - делать деньги.
3. Если вы программист - делать вид, что так было задумано.
Ответить с цитированием
  #3  
Старый 11.01.2008, 16:02
~ SaM ~ ~ SaM ~ вне форума
Начинающий
 
Регистрация: 05.01.2007
Адрес: Днепропетровск
Сообщения: 141
Репутация: 25
По умолчанию

Это пример процедур, которые долго работают. Пока их только 13 и все они имеют приблизительно одинаковую структуру.
Код:
Procedure FirstVed_add_2;
Var i,j:integer;
begin
j:=j-8;
for i:=1 to 15 do begin
j:=j+8;
Setrange(1,'Q'+inttostr(125-j),'');
Setrange(1,'Q'+inttostr(126-j),'');
Setrange(1,'W'+inttostr(125-j),'');
Setrange(1,'W'+inttostr(126-j),'');
Setrange(1,'W'+inttostr(121-j),'');
Setrange(1,'W'+inttostr(122-j),'');
Setrange(1,'X'+inttostr(121-j),'');
Setrange(1,'X'+inttostr(122-j),'');
SetBorderRange(1,'S'+inttostr(125-j)+':V'+inttostr(125-j),xlEdgeBottom,xlDashDot,xlThin,0,rgb(255,255,255));
SetBorderRange(1,'S'+inttostr(126-j)+':V'+inttostr(126-j),xlEdgeBottom,xlDashDot,xlThin,0,rgb(255,255,255));
SetBorderRange(1,'X'+inttostr(125-j)+':Y'+inttostr(125-j),xlEdgeBottom,xlDashDot,xlThin,0,rgb(255,255,255));
SetBorderRange(1,'S'+inttostr(126-j)+':Y'+inttostr(126-j),xlEdgeBottom,xlDashDot,xlThin,0,rgb(255,255,255));
SetBorderRange(1,'X'+inttostr(121-j)+':Y'+inttostr(121-j),xlEdgeTop,xlDashDot,xlThin,0,rgb(255,255,255));
SetBorderRange(1,'X'+inttostr(121-j)+':Y'+inttostr(121-j),xlEdgeLeft,xlDashDot,xlThin,0,rgb(255,255,255));
SetBorderRange(1,'X'+inttostr(121-j)+':Y'+inttostr(121-j),xlEdgeRight,xlDashDot,xlThin,0,rgb(255,255,255));
SetBorderRange(1,'X'+inttostr(122-j)+':Y'+inttostr(122-j),xlEdgeLeft,xlDashDot,xlThin,0,rgb(255,255,255));
SetBorderRange(1,'X'+inttostr(122-j)+':Y'+inttostr(122-j),xlEdgeRight,xlDashDot,xlThin,0,rgb(255,255,255));
SetBorderRange(1,'X'+inttostr(123-j)+':Y'+inttostr(123-j),xlEdgeBottom,xlDashDot,xlThin,0,rgb(255,255,255));
SetBorderRange(1,'X'+inttostr(123-j)+':Y'+inttostr(123-j),xlEdgeLeft,xlDashDot,xlThin,0,rgb(255,255,255));
SetBorderRange(1,'X'+inttostr(123-j)+':Y'+inttostr(123-j),xlEdgeRight,xlDashDot,xlThin,0,rgb(255,255,255));
end;

j:=-8;
for i:=1 to 15 do begin
j:=j+8;
Setrange(1,'F'+inttostr(125-j),'');
Setrange(1,'F'+inttostr(126-j),'');
Setrange(1,'L'+inttostr(125-j),'');
Setrange(1,'L'+inttostr(126-j),'');
Setrange(1,'M'+inttostr(121-j),'');
Setrange(1,'M'+inttostr(122-j),'');
SetBorderRange(1,'H'+inttostr(125-j)+':K'+inttostr(125-j),xlEdgeBottom,xlDashDot,xlThin,0,rgb(255,255,255));
SetBorderRange(1,'H'+inttostr(126-j)+':K'+inttostr(126-j),xlEdgeBottom,xlDashDot,xlThin,0,rgb(255,255,255));
SetBorderRange(1,'M'+inttostr(125-j)+':N'+inttostr(125-j),xlEdgeBottom,xlDashDot,xlThin,0,rgb(255,255,255));
SetBorderRange(1,'M'+inttostr(126-j)+':N'+inttostr(126-j),xlEdgeBottom,xlDashDot,xlThin,0,rgb(255,255,255));
SetBorderRange(1,'M'+inttostr(121-j)+':N'+inttostr(121-j),xlEdgeTop,xlDashDot,xlThin,0,rgb(255,255,255));
SetBorderRange(1,'M'+inttostr(121-j)+':N'+inttostr(121-j),xlEdgeLeft,xlDashDot,xlThin,0,rgb(255,255,255));
SetBorderRange(1,'M'+inttostr(121-j)+':N'+inttostr(121-j),xlEdgeRight,xlDashDot,xlThin,0,rgb(255,255,255));
SetBorderRange(1,'M'+inttostr(122-j)+':N'+inttostr(122-j),xlEdgeLeft,xlDashDot,xlThin,0,rgb(255,255,255));
SetBorderRange(1,'M'+inttostr(122-j)+':N'+inttostr(122-j),xlEdgeRight,xlDashDot,xlThin,0,rgb(255,255,255));
SetBorderRange(1,'M'+inttostr(123-j)+':N'+inttostr(123-j),xlEdgeBottom,xlDashDot,xlThin,0,rgb(255,255,255));
SetBorderRange(1,'M'+inttostr(123-j)+':N'+inttostr(123-j),xlEdgeLeft,xlDashDot,xlThin,0,rgb(255,255,255));
SetBorderRange(1,'M'+inttostr(123-j)+':N'+inttostr(123-j),xlEdgeRight,xlDashDot,xlThin,0,rgb(255,255,255));
end;
end;

Вот процедура, которая через потоки вызывает необходимые процедуры:
Код:
Procedure FirstVed;
Var i,j:integer;
    h1:cardinal;
begin
if strtoint(vidor_vdm_form.label11.Caption)Ю0 then begin
CreateThread(nil,0,@FirstVed_add_1,nil,0,h1) ;
..................
CreateThread(nil,0,@FirstVed_add_13,nil,0,h1) ;
end;
end;

И процедура, которая все это вызывает:
Код:
if not CreateExcel then exit;
j:=0;
jj:=0;
OpenWorkBook(getcurrentdir+'\ADP_VED\template_1.xls');
for i:=1 to vidor_vdm_form.listbox1.Items.Count-1 do begin
if i mod 2=1 then begin
j:=j+8;
SetRange(1,'G'+inttostr(j),vidor_vdm_form.listbox1.Items.Strings[i]);
SetRange(1,'G'+inttostr(j+1),vidor_vdm_form.listbox2.Items.Strings[i]);
end;
if i mod 2=0 then begin
jj:=jj+8;
SetRange(1,'R'+inttostr(jj),vidor_vdm_form.listbox1.Items.Strings[i]);
SetRange(1,'R'+inttostr(jj+1),vidor_vdm_form.listbox2.Items.Strings[i]);
end;
end; 

FirstVed; //процедура, работающая с потоками

VisibleExcel(true);
PrintPreviewEx;
SaveWorkBookAs(getcurrentdir+'\VDM\'+datetostr(date)+'.vdm');
CloseWorkBook;
CloseExcel;

Результат работы выполнения во вложении:
Изображения
Тип файла: jpg error.jpg (31.1 Кбайт, 19 просмотров)
Ответить с цитированием
  #4  
Старый 11.01.2008, 16:07
~ SaM ~ ~ SaM ~ вне форума
Начинающий
 
Регистрация: 05.01.2007
Адрес: Днепропетровск
Сообщения: 141
Репутация: 25
По умолчанию

При пошаговом выполнении программы, ошибка вылетает на
Код:
CreateThread(nil,0,@FirstVed_add_1,nil,0,h1) ;

P.S. Может я неправильно сделал/оформил/написал сами потоки??? Да, и при использовании процедур в процедуре FirstVed без потоков, то все работает без проблем, но очень долго.

Надеюсь на помощь!

Заранее спасибо!
Ответить с цитированием
  #5  
Старый 12.01.2008, 12:35
ART ART вне форума
Продвинутый
 
Регистрация: 13.02.2006
Адрес: Магнитогорск
Сообщения: 669
Репутация: 14745
По умолчанию

Создание потоков не увеличит скорость выполнения процедур и функций. Надо оптимизировать.
Ответить с цитированием
  #6  
Старый 12.01.2008, 13:21
~ SaM ~ ~ SaM ~ вне форума
Начинающий
 
Регистрация: 05.01.2007
Адрес: Днепропетровск
Сообщения: 141
Репутация: 25
По умолчанию

to ART

Да, я с тобой согласен, что процедура/функция не будет работать быстрее из-за того, что она будет выполняться в отдельном протоке! Но!!! Вопрос ведь заключается в другом... У меня таких процедур(практически с одинаковой структурой) пока только 13, а в конечном итоге должно быть от 20 до 30. И ведь если все эти процедуры будут выполняться через COM в многопоточности(Multithreaded(MTA)), то это существенно увеличит время выполнения.

Ломал я голову, лазил по инэту и нашел интересную статейку, в которой расказывается про однопоточность и многопоточность... В ней рассказывается, что при работе с COM (с потоками) необходимо инициализировать отдельный поток, т.к. COM по умолчанию(да и Delphi нас снабжает модулем ComObj.pas, который позволяет работать только в однопоточном режиме...) работает только с одним потоком информации(грубо говоря очередь выстраивается )...

Теперь если посмотреть дальше, то не трудно понять что дополнительные потоки необходимо инициализировать при помощи такого кода:

Код:
CoInitializeEx (NIL, COINIT_MULTITHREADED); //создаем дополнительный поток
//выполнение созданного потока
CoUninitialize; //Даем понять COM'у , что этот поток выполнил все что от него требуется и его можно отключать, для последующего(если требуется) повторного запуска.

Для использования CoInitializeEx и CoUninitialize необходимо подключать модуль ActiveX.

Что из этого происходит:

Инициализвация(создание) новго потока проходит без вопросов, первы поток начинает выполнение, и после того, как инициализируется втрой - COM отключается от программы и пишет "не инициализирован CoInitializeEx"

Так вот НАДЕЮСЬ, что загвоздка осталась именно в инициализации потока для MTA.

Написал код для STA. Вот что получилось:
Код:
  TSTAAutoObjectFactory = class(TAutoObjectFactory,     IClassFactory)
    function CreateInstance;
  end;

  TSTAThread = class (TThread)
    procedure Execute; override;
  end;

//
function TSTAAutoObjectFactory.CreateInstance;
begin
  Создает TSTAThread, заставляет поток STA создать затребованный объект,и ждет, пока поток STA успешно создаст объект, после чего возвращает созданный экземпляр в качестве результата этого метода
end;

Выполнение:
Код:
procedure TSTAThread.Execute;
begin
  // Вход в STA
  CoInitializeEx (NIL, COINIT_APARTMENTTHREADED);
//  Создает экземпляр, затребованный TSTAAutoObjectFactory;
//  Сигнализирует потоку TSTAAutoObjectFactory.CreateInstance, что 
//  экземпляр теперь доступен
//  Вход в цикл сообщений STA
  CoUninitialize; //  Выход из STA
end;

Работает без вопросов! Все отлично! Но это STA(однопоточность)...

Стоит сделать многопоточность - сразу вылетает ошибка, что потоки не инициализированы!

Подскажите, что я не правильно делаю!!!???
Ответить с цитированием
  #7  
Старый 12.01.2008, 13:23
~ SaM ~ ~ SaM ~ вне форума
Начинающий
 
Регистрация: 05.01.2007
Адрес: Днепропетровск
Сообщения: 141
Репутация: 25
По умолчанию

Если как-то заумно написал, то вкратце это звучит так:

Необходимо выполнять в COM(в данном случае работа с Excel) несколько потоков ОДНОВРЕМЕННО!!!

Надеюсь на помощь...
Ответить с цитированием
  #8  
Старый 28.02.2008, 22:04
Wadimus Wadimus вне форума
Прохожий
 
Регистрация: 28.02.2008
Адрес: Днепр
Сообщения: 2
Репутация: 10
По умолчанию

Пробовал использовать эти процедуры для создания списка компьютеров в отдельном потоке (уж очень надолго вешает программу при однопоточности)
При создании формы создаю отдельный поток:

CoInitializeEx (NIL, COINIT_MULTITHREADED);

периодически опрашиваю сеть:

CreateThread(nil, 0, @UpdateHostList, nil, 0, h1);

После такого опроса возникает ошибка при переходе по страницам PageControl "Недопустимый дескриптор окна" и ошибка при попытке закрыть программу.

Мож кто скажет, как правильно использовать эти три процедуры(в каком порядке), чтобы избежать ошибки:
CoInitializeEx, CreateThread, CoUninitialize.
Ответить с цитированием
  #9  
Старый 29.02.2008, 11:06
Phedor Phedor вне форума
Начинающий
 
Регистрация: 28.02.2008
Сообщения: 118
Репутация: 21
По умолчанию

Цитата:
Сообщение от ~ SaM ~
Если как-то заумно написал, то вкратце это звучит так:

Необходимо выполнять в COM(в данном случае работа с Excel) несколько потоков ОДНОВРЕМЕННО!!!

Надеюсь на помощь...
Попробуй использовать DDE, по результатам тестов это самый быстрый способ работы со сторонними приложениями, хоть и не такой удобный.
Если баотаешь с Excel, то создавай временный массив работай с ним, а результат кидай через Range.
Ответить с цитированием
  #10  
Старый 29.02.2008, 13:14
~ SaM ~ ~ SaM ~ вне форума
Начинающий
 
Регистрация: 05.01.2007
Адрес: Днепропетровск
Сообщения: 141
Репутация: 25
По умолчанию

Phedor

Если я правильно понял, то имеешь ввиду заливать данные матрицей. Это без вопросов. В конечном итоге я так и сделал, но самое противное, что после заполнения данными начинают перерисовываться ячейки (т.е. чтобы она была с контурами, перечеркнутая и т.д.). А матрицей не получится такое организовать, т.к. разных "видов" ячеек до 15. Решил я проблему очень банально. Создал шаблоны с разными видами ячеек и перед заполнением данными открываю тот шаблон, который мне нужен. Конечно это не выход в данной ситуации, но мне ничего не оставалось, т.к. с многопоточность я не смог разобраться, хотя очень хочу!
Ответить с цитированием
  #11  
Старый 29.02.2008, 15:44
Phedor Phedor вне форума
Начинающий
 
Регистрация: 28.02.2008
Сообщения: 118
Репутация: 21
По умолчанию

Цитата:
Сообщение от ~ SaM ~
Phedor

Если я правильно понял, то имеешь ввиду заливать данные матрицей. Это без вопросов. В конечном итоге я так и сделал, но самое противное, что после заполнения данными начинают перерисовываться ячейки (т.е. чтобы она была с контурами, перечеркнутая и т.д.). А матрицей не получится такое организовать, т.к. разных "видов" ячеек до 15. Решил я проблему очень банально. Создал шаблоны с разными видами ячеек и перед заполнением данными открываю тот шаблон, который мне нужен. Конечно это не выход в данной ситуации, но мне ничего не оставалось, т.к. с многопоточность я не смог разобраться, хотя очень хочу!
1. Бордюры и цвета тоже можно делать через Range.
2. Долго это конечно, но проверте не показываете ли вы саму перерисовку. Сначала создаем соединение, выводим, а потом уже показываем. Проверял, если сначала Show сделать, а потом рисовать примерно в 15 раз медленее получается.
3. Многопоточность. Попробуйте выводить разные блоки инфы в разных потоках. В главном только открытие и закрытие COM-сессии.
Ответить с цитированием
  #12  
Старый 29.02.2008, 19:40
~ SaM ~ ~ SaM ~ вне форума
Начинающий
 
Регистрация: 05.01.2007
Адрес: Днепропетровск
Сообщения: 141
Репутация: 25
По умолчанию

Phedor

1. Не знал.
2. Так и делаю.
3. У меня и есть разные блоки в разных потоках, но все-равно СОМ меня не пускает!

Принцип построения алгоритма:

1.Основной поток, отвечающий за открытие/закрытие/отображение Excel
2. Выполняется основной код, разбитый на блоки (разные потоки), которых 32. Первый поток заполняет данными лист, второй, третий, ..., двадцать седьмой - разрисовывает ячейки. Разрисовывать надо очень много, поэтому столько потоков на отрисовку... После рисования и заполнения данными - 28,29,30,31,32 потоки строят диаграммы на основании введенных данных... ну их соответственно 5.

Я объяснил сухо конечно, но у меня нет возможности показать код, т.к. он дома, а я еще неделю в командировке!

Когда мне ставили задачу, то необходим был именно Excel. Мол так удобнее просматривать, чем в стринггриде, да и примитивные диаграммы(TChar'ты) выглядят плохо... Короче нужен Excel.

Фух... написал...
Ответить с цитированием
  #13  
Старый 05.03.2008, 16:44
Wadimus Wadimus вне форума
Прохожий
 
Регистрация: 28.02.2008
Адрес: Днепр
Сообщения: 2
Репутация: 10
Восклицание Проблема при использовании потоков

Нашел бок при использовании потоков.
При выделении памяти в отдельном потоке(с последующим ее освобождением) происходит потеря связи приложения с окнами.
("Недопустимый дескриптор окна" и др.)

Сначало проявилось на стандартной функции
TList.add(Item: Pointer): integer.
Пробовал сделать свой клас-список, не помогло, тот же бок.
Стоит убрать работу с памятью - и все ОК.

Кто-нидь скажет: ЭТО чем-то лечится?
Ответить с цитированием
Ответ


Delphi Sources

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

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

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

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


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


 

Сайт

Форум

FAQ

RSS лента

Прочее

 

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

ВКонтакте   Facebook   Twitter