Форум: "Начинающим";
Текущий архив: 2009.05.03;
Скачать: [xml.tar.bz2];
ВнизИспользование крит.секции Найти похожие ветки
← →
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;
Скачать: [xml.tar.bz2];
Память: 0.51 MB
Время: 0.007 c