Форум: "Начинающим";
Текущий архив: 2015.02.08;
Скачать: [xml.tar.bz2];
ВнизЯ никак не пойму в чем секрет, не работает DataSet Найти похожие ветки
← →
вова (2014-01-04 18:46) [0]Начинается все вот так:
destructor TObjectList.Destroy;
var
i: integer;
begin
FCount := 0;
SetLength(fTObjectsList, 0);
fTObjectsList := nil;
with GlobalShot do
begin
if not suspended then
begin
WaitForSingleObject(GlobalShot.MyMutex, INFINITE);
Terminate;
ReleaseMutex(GlobalShot.MyMutex);
// WaitFor;
end;
Free;
end;
if Length(fTObjectsList) > 0 then
for i := 0 to Length(fTObjectsList) - 1 do
begin
with fTObjectsList[i] do
begin
if not suspended then
begin
Terminate;
WaitFor;
end;
Free;
end;
end;
FCapacityAlph := 0;
FCountAlph := 0;
if Length(fTAlphabetsList) > 0 then
for i := 0 to Length(fTAlphabetsList) - 1 do
begin
fTAlphabetsList[i].Free;
end;
inherited;
end;
И код успешно доходит до fTAlphabetsList[i].Free; и заходит внутрь. Причем объекты в fTAlphabetsList это класс выполняющийся в основном потоке. А деструкторы классов которые удаляются выше с DataSet не работают. Да и в процессе своей работы тоже.
и вотdestructor TTextRecognize.Destroy;
begin
Form3.InsertNewSamplesInAlphabetSampleMassive(fName,fUnknownSymbols);
........
inherited;
end;
мы вызываем процедуру которая работает с DataSet в деструкторе класса.
в этой процедуре есть всего 2 места где идет обращение к DataSetFunction TForm3.InsertNewSamplesInAlphabetSampleMassive(ObjectName: String;
UnknownSymbolsArray: TSimpleSearchArray): boolean;
var
BufX: TSimpleSearchArray;
fSizeUS: integer;
pStart, pStop, pBuff: pWord;
m: word;
begin
UniFindRecord("ClientDataSet1", "Name", ObjectName)
...........................
InsertNewSampleInDataSet3("KonturPicture", BufX) // вставляем
..........................
end;
Первая из них замечательно отрабатывает, на этот раз.function TForm3.UniFindRecord(NameDataSet, ColName, ColValue: String): boolean;
Begin
If (not(GetDataSetParametr(NameDataSet, ColName) = ColValue)) then
begin
If not TClientDataSet(FindComponent(NameDataSet))
.Locate(ColName, ColValue, []) then
begin
if Debug then
MessageDlg("Значение " + ColValue + " в колонке " " + ColName +
" " не найдено, добавьте в базу данных запись с таким значением в этой колонке!",
mtError, [mbOK], 0);
result := false;
end
else
result := true;
end
else
result := true;
end;
а во второй, я пытаюсь вычислить новый индекс строки для новой записи
maxSimb := GetMax_ImIndexClientDataSet3();Function TForm3.GetMax_ImIndexClientDataSet3(): integer;
var
maxSimb: integer;
ObjectName :string;
begin
// Уникальность по всей базе
GetMax_ImIndexClientDataSet3 := 0;
maxSimb := 0;
ObjectName := GetDataSetParametr("ClientDataSet1", "Name");
if ClientDataSet3.Filtered then
ClientDataSet3.Filtered := false;
//Form3.ClientDataSet1.DisableControls;
//Form3.ClientDataSet3.DisableControls;
Form3.ClientDataSet1.Last;
While Not Form3.ClientDataSet1.Bof Do
begin
Form3.ClientDataSet3.First;
While Not Form3.ClientDataSet3.Eof Do
begin
if ClientDataSet3.FieldByName("_ImIndex").value = Null then
begin
Form3.ClientDataSet3.Next;
continue;
end;
if Form3.ClientDataSet3.FieldByName("_ImIndex").value > maxSimb then
maxSimb := Form3.ClientDataSet3.FieldByName("_ImIndex").value;
Form3.ClientDataSet3.Next;
end;
Form3.ClientDataSet1.Prior;
end;
//Form3.ClientDataSet3.EnableControls;
//Form3.ClientDataSet1.EnableControls;
ClientDataSet1.Locate("Name", ObjectName, []);
//UniFindRecord("ClientDataSet1", "Name", ObjectName);
GetMax_ImIndexClientDataSet3 := maxSimb;
end;
т.к. обнаружилось, что почему-то фокус с элемента ClientDataSet1 слетает после этой процедуры, то я запоминаю имя на котором мы были до выполнения процедуры: ObjectName := GetDataSetParametr("ClientDataSet1", "Name");
И пытаемся восстановить его после (первый вариант, упрощенный от второго, дает тот же результат)
ClientDataSet1.Locate("Name", ObjectName, []);
или UniFindRecord("ClientDataSet1", "Name", ObjectName);
и получаем ошибку First chance exception at $004033F9. Exception class $C0000005 with message "access violation at 0x004033f9: read of address 0x0000fffc". Process ******.exe (5224)
зато если просто вызватьprocedure TForm3.Button4Click(Sender: TObject);
var
BufX: TSimpleSearchArray;
begin
SetLength(BufX, 5);
UniFindRecord("ClientDataSet1", "Name", "LightGray");
//Form3.GetMax_ImIndexClientDataSet3(); а можно и так вызвать тоже работает.
InsertNewSampleInDataSet3("KonturPicture", BufX);
UniFindRecord("ClientDataSet1", "Name", "LightGray");
end;
то все пучком и все добавляется.....
че за фигня?
Причем если просто вызвать
← →
вова (2014-01-04 21:02) [1]external exception 80000003
или так....
← →
RWolf © (2014-01-04 22:17) [2]для начала, Replace in files: « Form3.» → « »
TObjectList — ведь есть уже класс в VCL с тем же именем, зачем эта путаница?
← →
вова (2014-01-04 23:40) [3]
> для начала, Replace in files: « Form3.» → « »
???
> TObjectList — ведь есть уже класс в VCL с тем же именем,
> зачем эта путаница?
кто ж знал что там есть.
← →
Настоящий Вова (2014-01-05 01:53) [4]
> вова (04.01.14 23:40) [3]
> > TObjectList — ведь есть уже класс в VCL с тем же именем,
> > зачем эта путаница?
>
>
> кто ж знал что там есть.
А что, компилятор ничего не сообщает?
← →
вова (2014-01-05 04:04) [5]нет не сообщает. И в этом проблемы нет. Проблема в корявом Dataset я уже все исковырял ( причем даже добился того, что ошибка то вылазит то нет. Т.е. с нного вызова попытка обращения к датасету вызывает исключение и ппц. но если понаставить пауз, то ошибок становится меньше ) может с потоками какая то ботва твориться (
И это я уже тут тыщу лет Вова, так что ты не настоящий )
← →
RWolf © (2014-01-05 04:15) [6]
> А деструкторы классов которые удаляются выше с DataSet не
> работают.
что где удаляется? элементы массива fTObjectsList удаляются?
нет, не удаляются.
потому что ещё выше по коду этот массив занулили, и все объекты просто потеряны.
← →
Сергей М. © (2014-01-05 12:25) [7]
> почему-то фокус с элемента ClientDataSet1 слетает
Странно как он, фокус, вообще там оказался)..
TClientDataSet - это же невизуальный элемент, о каком "фокусе" можно при этом рассуждать ?)
← →
вова (2014-01-05 12:26) [8]
что где удаляется? элементы массива fTObjectsList удаляются?
нет, не удаляются.
потому что ещё выше по коду этот массив занулили, и все объекты просто потеряны.
это я уже исправил, это ничего не меняет. DataSet используется как база данных, из него берутся данные в начале, т.е. в конструкторах класса он используется и все. После того как классы созданы в дата сет они не лезут. И вот тут в единственном месте я попытался записать обратно новые данные......вот результат ( хоть свой дата сет пиши (
← →
вова (2014-01-05 12:30) [9]
> Странно как он, фокус, вообще там оказался)..
> TClientDataSet - это же невизуальный элемент, о каком "фокусе"
> можно при этом рассуждать ?)
эм....визуализируется он через грид. Но эт неважно, в нем есть функции поиска или перебора в цикле его значений и одна из строк активная же.
Впрочем я вообще коментарил эту процедуру, все равно DataSet заклинивает, просто позже где то )
← →
вова (2014-01-05 13:15) [10]ну вот.....грохнул ту часть которая создает тот массив что удаляется тут
if Length(fTObjectsList) > 0 then
for i := 0 to Length(fTObjectsList) - 1 do
begin
with fTObjectsList[i] do
begin
if not suspended then
begin
Terminate;
WaitFor;
end;
Free;
end;
end;
и ошибка пропала. Как блин так! ведь стоит же WaitFor; и когда мы заходим в третью часть второй уже нет вообще по идее, как она вообще влияет на дальше происходящее (
← →
вова (2014-01-05 13:45) [11]да и это, во всех экспериментах тот класс не запускался в отдельном потоке, т.е. все операции на самом деле в основном.
with GlobalShot do
ток этот в потоке
begin
if not suspended then
begin
WaitForSingleObject(GlobalShot.MyMutex, INFINITE);
Terminate;
ReleaseMutex(GlobalShot.MyMutex);
// WaitFor;
end;
Free;
end;
← →
вова (2014-01-05 13:46) [12]но он вообще ничего не делает с DataSet никогда.
← →
Сергей М. © (2014-01-05 13:57) [13]Отладчик что говорит ?
← →
вова (2014-01-05 15:00) [14]доходит до
ClientDataSet1.Locate("Name", ObjectName, []);
и следующим этапом вываливает что нибудь типа этого
> и получаем ошибку First chance exception at $004033F9. Exception
> class $C0000005 with message "access violation at 0x004033f9:
> read of address 0x0000fffc". Process ******.exe (5224)
причем после этого момента дата сет на любые манипуляции так реагировать начинает.
← →
Настоящий Вова (2014-01-05 15:05) [15]
> read of address 0x0000fffc
Пытаешься обратиться к ещё не созданному объекту или уже уничтоженому. Или обращаешься к индексу массива превышающего его размер.
← →
Сергей М. © (2014-01-05 15:07) [16]И все эти чудеса, как ты утверждаешь, происходят не иначе как в основном потоке ? Т.е. никакие доп.потоки в этом и при этом вообще не участвуют, так ?
← →
вова (2014-01-05 15:17) [17]ну выходит так.....потому как я создаю класс TMyObject = class(TThread) который и содержится в fTObjectsList[i], но в resume я не делаю и execute он не выполняет.
а GlobalShot в отдельном потоке, но не контактирует с DataSet, т.е. в нем вообще ниодного обращения к нему нет, только TMyObject обращается к GlobalShot и забирает с него данные переодически и все.
кроме того как показала практика если массив TMyObject не создавать, то и ошибки нет....
← →
вова (2014-01-05 15:19) [18]
> Пытаешься обратиться к ещё не созданному объекту или уже
> уничтоженому. Или обращаешься к индексу массива превышающего
> его размер.
я вызываю ClientDataSet1.Locate("Name", ObjectName, []); это....поэтому это не я пытаюсь обратиться к уже уничтоженному или что то там еще. Что я могу с этим поделать то? ) кроме того если потом зайти в базу, то строка с таким именем там замечательно существует.
← →
Сергей М. © (2014-01-05 15:23) [19]
> ну выходит так
Да вот нифига не выходит, по твоим же утверждениям..
Перед вызовом Locate() сравни GetCurrentThreadId c MainThreadId и удивись.
← →
вова (2014-01-05 15:24) [20]форма с дата сетами существует все время, что существует программа и освобождается только вместе с закрытием программы. Никогда я не пытался освобождать их и даже удалять из них что-то програмно.
← →
sniknik © (2014-01-05 15:35) [21]> кроме того как показала практика если массив TMyObject не создавать, то и ошибки нет....
странная такая зависимость... и еще страньше что этот самый массив не участвует в обсуждении.
а вообще, что за фигня? зачем вопросы раз уверен, что у тебя все правильно? значит чудо, не спрашивай, фиксируй, и в Рим на канонизацию!
← →
вова (2014-01-05 16:20) [22]
if GetCurrentThreadId = MainThreadId then
ClientDataSet1.Locate("Name", ObjectName, [])
else
maxSimb := maxSimb;
попробовал делать так, в else ниразу не попал, но и ошибка не вылазит в этом месте, ну то есть она теперь вылазит такая же и при такой же операции но в другом коде...
TMyObject = class(TThread) также обнаружил "блуждающий" глюк в этом классе, раньше он иногда появлялся, а теперь стабильно, не освобождается в деструкторе Tbitmap, а вылетает с ошибкой закоментировал уничтожение. результат выше.
Ладно буду курить всю эту хрень (
← →
вова (2014-01-05 18:59) [23]...вообщем с GetCurrentThreadId = MainThreadId я не удивился, они одинаковые перед любой ошибкой.
← →
вова (2014-01-05 19:55) [24]поток точно один, убрал GlobalShot вообще, в результате в TMyObject = class(TThread) работает только конструктор и деструктор.
в fTAlphabetsList (в котором содержаться TTextRecognize = class)убрал вставление записей в дата Сет. Осталось только чтение в конструкторе. Впрочем как выяснилось, если не убирать то эффект будет тот же.
Результат: TMyObject вылетает в конструкторе с той же ошибкой. причем во второй итерации только, т.е. первый раз все выполняется, а второй уже ошибка. при условии, что сначала вызывается конструктор TTextRecognize = class, который также читает данные из дата сета.
А вот если вызов конструктора TMyObject будет перед TTextRecognize то тогда не вылетает ошибка, зато тогда нажатие на кнопку закончить отладку в RAD Studio приводит к зависанию делфи а через некоторое время выдает табличку что не удалось завершить процесс и выходим по аборту.... А если долго в цикле будет крутиться Create Free то в конце ошибка, что невозможно создать поток (
и я не понял, пока я не запустил Resume класс TMyObject = class(TThread) выполняется в основном потоке? Т.е. когда я вызываю из другого места его метод, то он будет вызван в основном потоке. ну а уж constructor TMyObject.Create(Name: string; Parent: TMyObject); тогда уж и тем более выполняется в основном потоке? тогда где может быть затык с DataSet?
или какая то там нить все равно создается и использовать его так не стоит? Потому что я тут уже этот вопрос задавал, ну то есть что в отдельный поток я его запускаю, только если он долго отрабатывает, а остальные экземпляры в основном работают. мне сказали можно так.....
← →
Сергей М. © (2014-01-05 20:08) [25]
> в TMyObject = class(TThread) работает только конструктор
> и деструктор
тогда нафих вообще нужен такой поток ?)
← →
вова (2014-01-05 20:20) [26]жесть
в конструкторе TTextRecognize есть функцияFunction TForm3.GetalphabetSampleMassive(ObjectName: String;
var sumBufX: TSimpleSearchArray; var TemplateStr: string): boolean;
var
BufX: TSimpleSearchArray;
vBlob: TStream;
fSizeUS: integer;
pStart, pBuff, PendBuff: pWord;
m: word;
begin
result := false;
If not UniFindRecord("ClientDataSet1", "Name", ObjectName) then
exit;
fSizeUS := 0;
m := High(m) - 1; // знак начала шаблона в массиве.
SetLength(sumBufX, 1);
pStart := @sumBufX[0];
Form3.ClientDataSet3.DisableControls;
Form3.ClientDataSet3.First;
While Not Form3.ClientDataSet3.Eof Do
begin
vBlob := ClientDataSet3.CreateBlobStream
(ClientDataSet3.FieldByName("massSample"), bmRead);
SetLength(BufX, vBlob.Size div SizeOf(word));
try
vBlob.Seek(0, soFromBeginning); // sереход в начало потока BLOB
vBlob.ReadBuffer(BufX[0], vBlob.Size);
finally
vBlob.free;
end;
if Length(BufX) < 4 then
begin
Form3.ClientDataSet3.Next;
continue;
end;
TemplateStr := TemplateStr + GetDataSetParametr("ClientDataSet3", "Object");
fSizeUS := fSizeUS + Length(BufX) + 1; { вычисляем новый размер массива, как
текущий размер + длина присоединяемого шаблона + место для m - знак начала
шаблона в массиве, и т.е. разделитель шаблонов }
SetLength(sumBufX, fSizeUS); // удлиняем массив
pStart^ := m;
// присваиваем ему значение признака начала нового символа в массиве
inc(pStart); // переходим на следующий элемент
pBuff := @BufX[0]; // становимся в первый элемент копируемого массива
PendBuff := @BufX[Length(BufX) - 1]; // запоминаем адрес последнего элемента
// шаблона
pStart^ := pBuff^;
repeat
inc(pStart);
inc(pBuff);
pStart^ := pBuff^;
until pBuff = PendBuff; // до тех пор, пока не дойдем до последнего элемента
Form3.ClientDataSet3.Next;
end;
Form3.ClientDataSet3.EnableControls;
result := true;
end;
так вот если в ней закоментировать вот этот кусокTemplateStr := TemplateStr + GetDataSetParametr("ClientDataSet3", "Object");
fSizeUS := fSizeUS + Length(BufX) + 1; { вычисляем новый размер массива, как
текущий размер + длина присоединяемого шаблона + место для m - знак начала
шаблона в массиве, и т.е. разделитель шаблонов }
SetLength(sumBufX, fSizeUS); // удлиняем массив
pStart^ := m;
// присваиваем ему значение признака начала нового символа в массиве
inc(pStart); // переходим на следующий элемент
pBuff := @BufX[0]; // становимся в первый элемент копируемого массива
PendBuff := @BufX[Length(BufX) - 1]; // запоминаем адрес последнего элемента
// шаблона
pStart^ := pBuff^;
repeat
inc(pStart);
inc(pBuff);
pStart^ := pBuff^;
until pBuff = PendBuff; // до тех пор, пока не дойдем до последнего элемента
то ошибка пропадает.....а что с этим куском не так?
← →
вова (2014-01-05 20:25) [27]даже можно вот это не коментировать
TemplateStr := TemplateStr + GetDataSetParametr("ClientDataSet3", "Object");
таким образом я в этом куске вообще не трогаю ДатаСет, чомля ему надо (
← →
вова (2014-01-05 20:28) [28]ААААААААААААААА я понял наверное, когда я увеличиваю размер массива, необязательно, что место будет выделено прямо после конца предыдущего, и в результате inc(pBuff) будет указывать хз куда, может там чо то и затирается...хотя странно, почему ошибка тогда все время одна и та же...
← →
RWolf © (2014-01-05 20:28) [29]
> и я не понял, пока я не запустил Resume класс TMyObject
> = class(TThread) выполняется в основном потоке?
класс нигде не выполняется. Выполняется код. Конкретно конструктор этого класса создаёт поток, исполняющий код метода TMyObject.Execute. Вызов Resume разбудит этот поток, если он ещё не работает (см. аргумент конструктора TThread).
← →
вова (2014-01-05 20:38) [30]переделал pStart^ на sumBufX[i], пока вроде все тихо......ларчик то просто окрывался ) ошибка вылетает в деструкторе, а косяк в конструкторе )) причем совсем в другом месте.....
> класс нигде не выполняется. Выполняется код. Конкретно конструктор
> этого класса создаёт поток, исполняющий код метода TMyObject.
> Execute. Вызов Resume разбудит этот поток, если он ещё не
> работает (см. аргумент конструктора TThread).
тады чо он так вешает все.......конечно в обычном режиме не предполагается непрерывное создание и уничтожение потоков, но мало ли кому чего в голову придет, а у меня ошибка вылетает тогда (
← →
RWolf © (2014-01-05 20:39) [31]
> [28]
когда увеличивается размер массива, старые указатели вообще бесполезны, потому что весь массив переместился.
не нужно использовать указатели там, где достаточно индексов.
← →
RWolf © (2014-01-05 20:39) [32]
> [28]
когда увеличивается размер массива, старые указатели вообще бесполезны, потому что весь массив переместился.
не нужно использовать указатели там, где достаточно индексов.
Страницы: 1 вся ветка
Форум: "Начинающим";
Текущий архив: 2015.02.08;
Скачать: [xml.tar.bz2];
Память: 0.56 MB
Время: 0.002 c