Главная страница
    Top.Mail.Ru    Яндекс.Метрика
Форум: "Начинающим";
Текущий архив: 2009.02.15;
Скачать: [xml.tar.bz2];

Вниз

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

 
Семен Кевларвестов   (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;
Скачать: [xml.tar.bz2];

Наверх





Память: 0.48 MB
Время: 0.005 c
15-1229590921
Calligraff
2008-12-18 12:02
2009.02.15
Непонятный глюк в Delphi


15-1229497529
nnov
2008-12-17 10:05
2009.02.15
icq 5.1


3-1214981127
BUM
2008-07-02 10:45
2009.02.15
LookUp поле по полю Calculate = 0


15-1229629312
DVM
2008-12-18 22:41
2009.02.15
А нет ли случаем такого готового класса?


15-1229870744
Кое кто
2008-12-21 17:45
2009.02.15
Интересная фраза (Не помню чья)





Afrikaans Albanian Arabic Armenian Azerbaijani Basque Belarusian Bulgarian Catalan Chinese (Simplified) Chinese (Traditional) Croatian Czech Danish Dutch English Estonian Filipino Finnish French
Galician Georgian German Greek Haitian Creole Hebrew Hindi Hungarian Icelandic Indonesian Irish Italian Japanese Korean Latvian Lithuanian Macedonian Malay Maltese Norwegian
Persian Polish Portuguese Romanian Russian Serbian Slovak Slovenian Spanish Swahili Swedish Thai Turkish Ukrainian Urdu Vietnamese Welsh Yiddish Bengali Bosnian
Cebuano Esperanto Gujarati Hausa Hmong Igbo Javanese Kannada Khmer Lao Latin Maori Marathi Mongolian Nepali Punjabi Somali Tamil Telugu Yoruba
Zulu
Английский Французский Немецкий Итальянский Португальский Русский Испанский