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

Вниз

Использование крит.секции   Найти похожие ветки 

 
T2k   (2009-03-18 15:05) [0]

Есть некоторый класс. Когда я вызываю некоторый метод этого класса, то создается дополнительный поток.
Этот поток работает с девайсом (считывает с него данные). По окончанию обмена я должен передать данные главной форме для сохранения в БД и завершить поток.
Так вот...предположим, что работает сразу несколько доп.потоков (считывают данные) и когда они завершаться я не могу знать. То ли одновременно , то ли по очереди.
Вопрос в следующем, нужна ли критическая секция в главной форме ? По коду,надеюсь, понятней будет


unit Unit1;
...
Obj:=TDial.Create;
Obj.OnData:=ModemData;

...
procedure TForm1.ModemData(CashID,Mode,TaskID,Res: DWord; ThreadObj: TObjectList);
begin
  EnterCriticalSection(CS); // ???
 // сохраняю данные в БД
  LeaveCriticalSection(CS); // ???
end;

unit DialUnit;

type
 TOnData  = procedure(CashID,Mode,TaskID,Res:DWord;ThreadObj:TObjectList) of object;

type
 TDial = class(TObject)
private
 FOnData:TOnData;
 ...
public
  procedure DoData(CashID,Mode,TaskID,Res:DWord;ThreadObj:TObjectList);
end;

procedure TDial.DoData(CashID,Mode,TaskID,Res: DWord; ThreadObj: TObjectList);
begin
 if Assigned(FOnData) then OnData(CashID,Mode,TaskID,Res,ThreadObj);
end;

//доп.поток
function TDial.FDeviceThread(...)
begin
 // получаю данные с девайса
  DoData(CashID,Mode,TaskID,Y,Obj); // выгрузить данные в главн.форму
end;



 
clickmaker ©   (2009-03-18 15:49) [1]

> данные главной форме для сохранения в БД

а зачем передавать именно форме?
она еще и отображением их по ходу занимается?


 
Сергей М. ©   (2009-03-18 16:08) [2]

Решение зависит от того, что скрывается за

> // сохраняю данные в БД


 
T2k   (2009-03-18 17:17) [3]

2 clickmaker ©   (18.03.09 15:49) [1]

Ну...не знаю. Я так сам решил. Ибо не знаю, как работать с БД из потока.
Мне проще с компонентами работать при работе с БД.

>она еще и отображением их по ходу занимается?
Нет. Только сохранение в БД и все. Отображение на другой программе.

2 Сергей М. ©   (18.03.09 16:08) [2]
> Решение зависит от того, что скрывается за

FireBird. Запись данных в пару таблиц. Код показать ?
Ну вот, например основной кусок :

...
ObjList.Clear;
   for I:=0 to ThreadObj.Count-1 do
   begin
     ObjList.Add(TStringList.Create);
     TStrings(ObjList.Items[I]).AddStrings(TStrings(ThreadObj.Items[I]));
   end;
   //
   Transact;
   IBSQL1.Close;
   IBSQL1.SQL.Clear;
   case Mode of
     0:begin   // товары
         IBSQL1.SQL.Add("DELETE FROM PLUREAD WHERE CASHID=:ID");
         IBSQL1.ParamByName("ID").AsInt64:=CashID;
         IBSQL1.ExecQuery;
       end;
     1:begin  // за день
         IBSQL1.SQL.Add("DELETE FROM DAYSALES WHERE CASHID=:ID AND DAYSALE=:DAY");
         IBSQL1.ParamByName("ID").AsInt64:=CashID;
         IBSQL1.ParamByName("DAY").AsDate:=Now;
         IBSQL1.ExecQuery;
       end;
     2:begin // с накоплением
         IBSQL1.SQL.Add("DELETE FROM DAYSALESTIME WHERE CASHID=:ID AND DAYSALE=:DAY");
         IBSQL1.ParamByName("ID").AsInt64:=CashID;
         IBSQL1.ParamByName("DAY").AsDate:=Now;
         IBSQL1.ExecQuery;
       end;
     3:begin  // нулевые остатки
         IBSQL1.SQL.Add("DELETE FROM ZEROPLU WHERE CASHID=:ID");
         IBSQL1.ParamByName("ID").AsInt64:=CashID;
         IBSQL1.ExecQuery;
       end;
     6:begin // начало/конец раб.дня
         if TStrings(ObjList.Items[0]).Count>0 then
         begin
           Memo1.Lines.Add("");
           Memo1.Lines.Add("Начало рабочего дня: "+TStrings(ObjList.Items[0]).Strings[0]);
           Memo1.Lines.Add("Конец рабочего дня: "+TStrings(ObjList.Items[0]).Strings[1]);
           Memo1.Lines.Add("");
         end;
       end;
     4:begin //запись
         if ObjList.Count>0 then
         begin
           for I:=0 to TStrings(ObjList.Items[0]).Count-1 do
           begin
             if TStrings(ObjList.Items[7]).Strings[I]="0" then
             begin
               if TryStrToInt(TStrings(ObjList.Items[8]).Strings[I],hInt) then
               begin
                 IBSQL1.Close;
                 IBSQL1.SQL.Clear;
                 IBSQL1.SQL.Add("DELETE FROM PLUWRITE WHERE ID=:HID");
                 IBSQL1.ParamByName("HID").AsInteger:=hInt;
                 IBSQL1.ExecQuery;
               end;
             end else
             begin
               if TryStrToInt(TStrings(ObjList.Items[8]).Strings[I],hInt) then
               begin
                 IBSQL1.Close;
                 IBSQL1.SQL.Clear;
                 IBSQL1.SQL.Add("UPDATE PLUWRITE SET TEXTERROR=:HTEXT WHERE ID=:HID");
                 IBSQL1.ParamByName("HID").AsInteger:=hInt;
                 if TryStrToInt(TStrings(ObjList.Items[7]).Strings[I],hTemp) then
                  IBSQL1.ParamByName("HTEXT").AsString:=GetDeviceError(hTemp) else
                   IBSQL1.ParamByName("HTEXT").AsString:="глобальная ошибка";
                 IBSQL1.ExecQuery;
               end;
             end;  
           end;
         end;
       end;

   end; // end case
   TransactCommit;
   Transact;
   //
   //SaveLog(" First Transact  Касса:"+IntToStr(CashID));
   // запись
   case Mode of
   1:begin // продажи за день
       for I:=0 to TStrings(ObjList.Items[0]).Count-1 do
       begin
         IBSQL1.SQL.Clear;
         //
         if STCIstokMode=0 then
         begin // обычная версия
           IBSQL1.SQL.Add("INSERT INTO DAYSALES VALUES(GEN_ID(IDDAYSALES,1),");
           IBSQL1.SQL.Add(":DAY,:CASH,:CODE,:NAME,:PRICE,:AMOUNT,:GRP,:TAX,:NSALE,:SSALE,:N PAY,:SPAY)");
         end;
         if STCIstokMode=1 then
         begin    // версия для Одессы
           IBSQL1.SQL.Add("INSERT INTO DAYSALES VALUES(GEN_ID(IDDAYSALES,1),:TASK,");
           IBSQL1.SQL.Add(":DAY,:CASH,:CODE,:NAME,:PRICE,:AMOUNT,:GRP,:TAX,:NSALE,:SSALE,:N PAY,:SPAY)");
           IBSQL1.ParamByName("TASK").AsInteger:=TaskID;
         end;
         //
         IBSQL1.ParamByName("DAY").AsDate:=Now;
         IBSQL1.ParamByName("CASH").AsInt64:=CashID;
         if not TryStrToInt64(TStrings(ObjList.Items[0]).Strings[I],hInt64) then hInt64:=0;
         IBSQL1.ParamByName("CODE").AsInt64:=hInt64;
         if Length(TStrings(ObjList.Items[1]).Strings[I])=0 then
          IBSQL1.ParamByName("NAME").Value:=null else
           begin
             hSt:= TStrings(ObjList.Items[1]).Strings[I];
             if Length(hSt)>25 then hSt:=Copy(hSt,1,25);
             IBSQL1.ParamByName("NAME").Value:=hSt;
           end;
         if not TryStrToFloat(TStrings(ObjList.Items[2]).Strings[I],hExt) then hExt:=0;
         IBSQL1.ParamByName("PRICE").AsFloat:=hExt;
         if not TryStrToFloat(TStrings(ObjList.Items[3]).Strings[I],hExt) then hExt:=0;
         IBSQL1.ParamByName("AMOUNT").AsFloat:=hExt;
         if not TryStrToInt(TStrings(ObjList.Items[6]).Strings[I],hInt) then hInt:=0;
         IBSQL1.ParamByName("GRP").AsInteger:=hInt;
         if not TryStrToInt(TStrings(ObjList.Items[7]).Strings[I],hInt) then hInt:=0;
         IBSQL1.ParamByName("TAX").AsInteger:=hInt;
         if not TryStrToFloat(TStrings(ObjList.Items[4]).Strings[I],hExt) then hExt:=0;
         IBSQL1.ParamByName("NSALE").AsFloat:=hExt;
         if not TryStrToFloat(TStrings(ObjList.Items[5]).Strings[I],hExt) then hExt:=0;
         IBSQL1.ParamByName("SSALE").AsFloat:=hExt;
         if not TryStrToFloat(TStrings(ObjList.Items[8]).Strings[I],hExt) then hExt:=0;
         IBSQL1.ParamByName("NPAY").AsFloat:=hExt;
         if not TryStrToFloat(TStrings(ObjList.Items[9]).Strings[I],hExt) then hExt:=0;
         IBSQL1.ParamByName("SPAY").AsFloat:=hExt;
         //
         IBSQL1.ExecQuery;
       end;
     end;



 
clickmaker ©   (2009-03-18 17:22) [4]

> [3] T2k   (18.03.09 17:17)
> 2 clickmaker ©   (18.03.09 15:49) [1]
>
> Ну...не знаю. Я так сам решил. Ибо не знаю, как работать
> с БД из потока.
> Мне проще с компонентами работать при работе с БД.

используй DataModule тогда


 
Сергей М. ©   (2009-03-18 17:24) [5]


> T2k   (18.03.09 17:17) [3]


FB требует как минимум отдельное соединение (отдельный объект TIBDatabase) на каждый тред, использующий это соединение для последующего доступа к объектам БД.

Этот требование тобой, похоже, не выполняется, так что дальнейший разговор про КС пока лишен смысла


 
T2k   (2009-03-18 17:34) [6]

2 Сергей М. ©   (18.03.09 17:24) [5]
FB требует как минимум отдельное соединение (отдельный объект TIBDatabase) на каждый тред, использующий это соединение для последующего доступа к объектам БД.

Погодите...У меня все доп.потоки передают данные главному. А из главного я и работаю с БД. Повторюсь...главные поток(читай Unit1.pas) работает c БД. Что не так ?

2 clickmaker ©   (18.03.09 17:22) [4]
> используй DataModule тогда

Хорошо. Я посмотрю в эту сторону. Но а чем мой вариант плох ???


 
Сергей М. ©   (2009-03-18 17:36) [7]


> У меня все доп.потоки передают данные главному


Где это видно из приведенного кода ?
Я этого не вижу, приведи цитату ..


 
T2k   (2009-03-18 17:40) [8]

2 Сергей М. ©   (18.03.09 17:36) [7]

Ну как в [0].
Работает доп.поток, накапливает данные в TObjectList. Далее вызывается событие  DoData, код которого расположен в unit1.pas. Разве я не прав ?


 
Сергей М. ©   (2009-03-18 17:58) [9]


> Далее вызывается событие  DoData, код которого расположен
> в unit1.pas


Так ведь в unit1 расположен код, а не кодовый поток (тред) !

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

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


 
clickmaker ©   (2009-03-18 18:19) [10]

> [6] T2k   (18.03.09 17:34)
>
> 2 clickmaker ©   (18.03.09 17:22) [4]
> > используй DataModule тогда
>
> Хорошо. Я посмотрю в эту сторону. Но а чем мой вариант плох
> ???

во-первых, при наличии большого числа компонентов БД на форме, ты в один прекрасный момент не сможешь раскопать визуальные, которые окажутся под ними.
ну а во-вторых - нормальное и логичное желание отделять работу с БД от интерфейса. Это не кажется актуальным, когда у тебя 2-3 эдита и один кверик, но на более серьезном проекте преимущества будут налицо, поверь


 
T2k   (2009-03-18 18:44) [11]

2 Сергей М. ©   (18.03.09 17:58) [9]

Спасибо. Теперь вроде понятно. Только опять таки вопрос...как правильно подойти к моей задаче ? Прямо из доп.потока сохранять данные в БД или как-то (сообщением или еще как) отправить данные из доп.потока главному и там(в главном) сохранять ?

2  clickmaker ©   (18.03.09 18:19) [10]

Спасибо, понял. Вот бы еще примерчик...как из потока работать с БД ;)
Хотя поищу...может что в инете есть.


 
Сергей М. ©   (2009-03-18 20:30) [12]


> Прямо из доп.потока сохранять данные в БД


> или как-то (сообщением или еще как) отправить данные из
> доп.потока главному и там(в главном) сохранять ?


Оба варианта имеют право на жизнь, выбирать тебе.
Хочу лишь заметить, что второй вариант - это как раз то что ты хотел добиться с пом. КС в изначальном вопросе.



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

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

Наверх




Память: 0.52 MB
Время: 0.015 c
15-1236055605
Дмитрий С
2009-03-03 07:46
2009.05.03
HotKey на всех Desktop-ах.


15-1235882735
KilkennyCat
2009-03-01 07:45
2009.05.03
Чтой-то было тут, пока я спал ? О_0


2-1237962304
Zalum
2009-03-25 09:25
2009.05.03
TreeView


2-1237725938
UNAT
2009-03-22 15:45
2009.05.03
Проблема с кодировкой/шрифтами во всех программах


2-1237900470
IIIakal
2009-03-24 16:14
2009.05.03
Помогите плиз разобраться с синтаксисом SQL запроса