Главная страница
Top.Mail.Ru    Яндекс.Метрика
Текущий архив: 2009.02.15;
Скачать: CL | DM;

Вниз

обработка данных КлиентДатасета в потоке   Найти похожие ветки 

 
Семен Кевларвестов   (2008-12-30 02:36) [0]

Доброй ночи!

Имеется нижеследующая ситуация: Есть грид (EhGrid), источников данных в нем служит ClientDataSet. Далее создается поток, в котором этот клиента пробегается от начала до конца и вызывается некая процедура. При это перед вызовом этой процедуры в поле со статусом клиентдатасета прописывается "Обработка началась", после - "Обработка завершена". Т.е., чтобы в гриде этот процесс обработки отображался и пользователь сильно не страдал.

В тред все это засунуто, видимо, чтобы процесс можно было обрубить, т.к. процедуры достаточно длительныя.

Но имеется такая нехорошая штука: при обработки длинных наборов данных вылетают ошибки всякий раз разные, то не тот индекс в гриде, то ошибка при отрисовке скроллбара, то вообще АВ в модуле. Я так понимаю, что это глючит отрисовка грида. Т.к. если перед началом выполнения потока грид скрыть, а потом показать - все выполняется без жертв.

Вопрос: можно ли вообще так работать с потоками/данными? И в чем может быть ошибка? Может где-то чего то синхронизировать надо? Или как-то иначе грид обновлять?.


 
Сергей М. ©   (2008-12-30 08:33) [1]


> можно ли вообще так работать с потоками/данными?


Нельзя.


> в чем может быть ошибка?


В том что грид связан с дейтасетом через дейтасурс и при этом работает в основном потоке.

А какой вообще смысл выносить работу с дейтасетом в доп.поток, если основной поток только тем и занят, что следит за телодвижениями доп.потока и визуализирует их в гриде ?
С тем же успехом все это можно сделять прямо в основном потоке ..


 
MsGuns ©   (2008-12-30 09:19) [2]

Запускать "пробежки" по визуализированному НД во вторичном потоке - штука крайне рискованная и требует блокировки ЛЮБЫХ перерисовок канвы (и не только). Поэтому если так уж надо "в потоке", то лучше создать клон (если датасет АДОшный) и по нему "бегать".


 
qqq   (2008-12-30 10:49) [3]

временно отцепи датасорс от датасета
м.б. поможет просто disablecontrols


 
Игорь Шевченко ©   (2008-12-30 13:55) [4]


> Имеется нижеследующая ситуация: Есть грид (EhGrid), источников
> данных в нем служит ClientDataSet. Далее создается поток,
>  в котором этот клиента пробегается от начала до конца и
> вызывается некая процедура. При это перед вызовом этой процедуры
> в поле со статусом клиентдатасета прописывается "Обработка
> началась", после - "Обработка завершена". Т.е., чтобы в
> гриде этот процесс обработки отображался и пользователь
> сильно не страдал.


 TCheckThread = class(TThread)
 private
   FMember: TMemberModel;
   FBadReason: string;
   FErrorMessage: string;
   procedure AddMemberToBadList;
   procedure AfterFillCDS;
   procedure ShowError;
 public
   constructor Create;
   procedure Execute; override;
 end;

procedure TdmMember.AddMemberToBadMemberList(ObjectData: TMemberModel;
 const AReason: string);
begin
 with cdsBadMembers do
 begin
   Append;
   try
     FieldByName("MEMBER_ID").AsInteger := ObjectData.ID;
     FieldByName("LAST_NAME").AsString := ObjectData.LastName;
     FieldByName("FIRST_NAME").AsString := ObjectData.FirstName;
     FieldByName("SECOND_NAME").AsString := ObjectData.SecondName;
     FieldByName("SEX").AsString := ObjectData.Sex;
     FieldByName("OBJECT_DATA").AsInteger := Integer(ObjectData);
     FieldByName("REASON").AsString := AReason;
     Post;
   except
     Cancel;
   end;
 end;
end;

procedure TCheckThread.AddMemberToBadList;
begin
 dmMember.AddMemberToBadMemberList (FMember, FBadReason);
end;

procedure TCheckThread.AfterFillCDS;
begin
 with dmMember.cdsBadMembers do
 begin
   DisableControls;
   try
     IndexName := "VIEWKEY";
     First;
   finally
     EnableControls;
   end;
 end;
end;

constructor TCheckThread.Create;
begin
 inherited Create (true);
 Priority := tpLower;
 FreeOnTerminate := true;
 Resume;
end;

procedure TCheckThread.Execute;
begin
 dmMember.CheckThreadRunning := true;
 with dmMember.qCheck do begin
   DisableControls;
   try
     if Active then
       First
     else
       Open;
     while not Eof and not Terminated do
     begin
       try
         dmMember.CheckedMembersCount := dmMember.CheckedMembersCount + 1;
         FMember := TMemberModel.Create;
         FMember.ID := FieldByName("MEMBER_ID").AsInteger;
         dmMember.LoadObject(FieldByName("MEMBER_ID").AsInteger, FMember);
         FBadReason := FMember.HasInconsistentData;
         if FieldByName("HASCARD").AsString = "N" then
         begin
           if FBadReason <> "" then
             FBadReason := FBadReason + ",";
           FBadReason := FBadReason + g_NoCard;
         end;
         if FBadReason <> "" then
           Synchronize(AddMemberToBadList)
         else
           FMember.Free;
       except
         on E: Exception do begin
           FErrorMessage := E.Message;
           Synchronize(ShowError);          
         end;
       end;
       Next;
     end;
   finally
     First;
     EnableControls;
   end;
 end;
 Synchronize(AfterFillCDS);  
 dmMember.CheckThreadRunning := false;
end;

procedure TCheckThread.ShowError;
begin
 ShowMessage(FErrorMessage);
end;


Все прекрасно работает, данные в гриде ползут по мере поступления, можно заниматься другими делами пока грид не заполнится.
Единственное - подключение к базе данных для датасетов, работа с которыми выполняется в потоке, я всегда делаю отдельное.


 
Loginov Dmitry ©   (2008-12-30 16:22) [5]

> Имеется нижеследующая ситуация: Есть грид (EhGrid), источников
> данных в нем служит ClientDataSet. Далее создается поток,
> в котором этот клиента пробегается от начала до конца и
> вызывается некая процедура. При это перед вызовом этой процедуры
> в поле со статусом клиентдатасета прописывается "Обработка
> началась", после - "Обработка завершена". Т.е., чтобы в
> гриде этот процесс обработки отображался и пользователь
> сильно не страдал.
>
> В тред все это засунуто, видимо, чтобы процесс можно было
> обрубить, т.к. процедуры достаточно длительныя.


для подобных задач как раз и разработан модуль progressviewer
(http://matrix.kladovka.net.ru/download.php?getfilename=uploads/other/progressviewer.zip)

В помощью него можно отказаться от потока, пользователь сможет видеть весь процесс обработки данных, и прервать его в любой момент. Код будет выглядеть примерно так:

DS.DisableControls;
try
 with TProgressViewer.Create("Обработка данных грида", True, True) do
 try
   DS.First;
   while not DS.Eof do
   begin
     CheckCancelByUser; // Если пользователь нажал "отмена", то генерируется исключение
     CurrentValue := (DS.RecNo / DS.RecordCount) * 100; // Выводим прогресс в процентах
     // ВЫПОЛНЯЕМ НЕОБХОДИМУЮ ОБРАБОТКУ
     DS.Next;
   end;
 finally
   Terminate; // завершаем поток визуализации
   DS.First;
 end;
finally
 DS.EnableControls;
end;



Страницы: 1 вся ветка

Текущий архив: 2009.02.15;
Скачать: CL | DM;

Наверх




Память: 0.5 MB
Время: 0.013 c
15-1229403089
Slider007
2008-12-16 07:51
2009.02.15
С днем рождения ! 16 декабря 2008 вторник


15-1229781796
Кое кто
2008-12-20 17:03
2009.02.15
Игра Praetorians


2-1231250146
Семён
2009-01-06 16:55
2009.02.15
Как изменить содержимое 2-й строки ListView без Clear?


2-1231171332
sh1k4r1
2009-01-05 19:02
2009.02.15
Excel + Delphi


15-1228919002
Добежал
2008-12-10 17:23
2009.02.15
Корректность считывания переменной из потоков