Форум: "Начинающим";
Текущий архив: 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