Главная страница
    Top.Mail.Ru    Яндекс.Метрика
Форум: "Начинающим";
Текущий архив: 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 места где идет обращение к DataSet

Function 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
2-1388846800
вова
2014-01-04 18:46
2015.02.08
Я никак не пойму в чем секрет, не работает DataSet


2-1389003648
Aleks
2014-01-06 14:20
2015.02.08
Установка начального каталога SelectDirectory


15-1404377324
xayam
2014-07-03 12:48
2015.02.08
Javascript to Java


15-1404823067
Павиа
2014-07-08 16:37
2015.02.08
NetBIOS или вирус?


15-1404312348
Minsk_City
2014-07-02 18:45
2015.02.08
Плагин для Notepad++ (форматтер кода)





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
Английский Французский Немецкий Итальянский Португальский Русский Испанский