当执行小于3的时候可以正常执行下去,结果也是对的;当循环大于4或者5时,App闪退了,try也捕捉不到异常(至少是看不到);代码如下: Mythreadtask1 := TTask.Create (procedure () var I,j,Lv:integer; begin try dpath:='1-';apath:='1-'; ClientModule1.ClientDataSet1.close; ClientModule1.ClientDataSet1.commandText:='select BasePath from B_Stock where BaseNo='''+ckid+''' '; ClientModule1.ClientDataSet1.Open; kpath:=ClientModule1.ClientDataSet1.FieldByName('BasePath').AsString; kpath:=kpath+'-'; // showmessage('Kpath:'+kpath); ClientModule1.ClientDataSet1.close; ClientModule1.ClientDataSet1.commandText:='select BasePath from B_Client where BaseNo='''+khid+''' '; ClientModule1.ClientDataSet1.Open; bpath:=ClientModule1.ClientDataSet1.FieldByName('BasePath').AsString; bpath:=bpath+'-'; // showmessage('bpath:'+bpath); ClientModule1.ClientDataSet1.close; ClientModule1.ClientDataSet1.commandText:='select BasePath from B_Person where BaseNo='''+empid+''' '; ClientModule1.ClientDataSet1.Open; epath:=ClientModule1.ClientDataSet1.FieldByName('BasePath').AsString; epath:=epath+'-'; // showmessage('Epath:'+Epath); // showmessage('表格条目: '+inttostr(ListView1.ItemCount)); lv:=ListView1.ItemCount; for I := 0 to Lv-1 do begin unitname:=ListView1.Items.AppearanceItem[I].Data['Text14'].AsString; sql:='select isnull(cast((case when BasicUnit='''+unitname+''' then 1 '; sql:=sql+' when AssistUniton_e='''+unitname+''' then 2 '; sql:=sql+' when AssistUnitTwo='''+unitname+''' then 3 '; sql:=sql+' when AssistUnitThree='''+unitname+''' then 4 end) as varchar(100)),'''+jb_yi+''') as unitindex, '; sql:=sql+' isnull(cast((case when BasicUnit='''+unitname+''' then PercentBasic '; sql:=sql+' when AssistUniton_e='''+unitname+''' then PercentOne'; sql:=sql+' when AssistUnitTwo='''+unitname+''' then PercentTwo'; sql:=sql+' when AssistUnitThree='''+unitname+''' then PercentThree end) as varchar (100)),'''+jb_yi+''') as huansuanlv '; sql:=sql+' from b_goods where baseno=cast('''+ListView1.Items.AppearanceItem[I].Data['Text9'].AsString+''' as int)'; ClientModule1.ClientDataSet1.Close; ClientModule1.ClientDataSet1.CommandText:= sql; ClientModule1.ClientDataSet1.Open; if ClientModule1.ClientDataSet1.RecordCount>0 then begin unitindex:=ClientModule1.ClientDataSet1.FieldByName('unitindex').AsString; unithuansuan:=ClientModule1.ClientDataSet1.FieldByName('huansuanlv').AsString; end else begin unitindex:='1'; unithuansuan:='1'; end; // showmessage('商品换算率执行完毕:'+unitindex+': '+unithuansuan); try ClientModule1.ClientDataSet1.close; ClientModule1.ClientDataSet1.commandText:='select BasePath from B_Goods where BaseNo='''+ListView1.Items.AppearanceItem[I].Data['Text9'].AsString+''' '; ClientModule1.ClientDataSet1.Open; ppath:=ClientModule1.ClientDataSet1.FieldByName('BasePath').AsString; ppath:=ppath+'-'; showmessage(inttostr(I)+' : '+Ppath);
sql:='select isnull(price,'''+jb_yi+''') as cb from S_GoodsInfo where ptypeid='''+ListView1.Items.AppearanceItem[I].Data['Text9'].AsString+''' '; showmessage(sql); ClientModule1.ClientDataSet1.Close; ClientModule1.ClientDataSet1.CommandText:=sql; showmessage('Ptypeid:' + ListView1.Items.AppearanceItem[I].Data['Text9'].AsString ); showmessage('开始执行:'+sql); ClientModule1.ClientDataSet1.Open; showmessage('执行结束:'+sql); if ClientModule1.ClientDataSet1.RecordCount>0 then begin cbdj:=ClientModule1.ClientDataSet1.FieldByName('cb').AsString; end else cbdj:='1'; showmessage('成本单价: '+cbdj); showmessage('数量 : '+ListView1.Items.AppearanceItem[I].Data['Text4'].AsString); cbje:=FormatFloat('0.00',0-(strtofloat(cbdj)*strtofloat(ListView1.Items.AppearanceItem[I].Data['Text4'].AsString)* strtofloat(unithuansuan))); showmessage('成本金额: '+cbje); except On E:Exception do showmessage(e.Message);
end;
try //My_Arrzh[0][0]是名称 kmid:='0000100001'; sqlz:=' insert into R_SaleDetail (Vchcode,atypeid,btypeid,'; sqlz:=sqlz+'etypeid,ktypeid,PtypeId,Qty,discount,'; sqlz:=sqlz+'DiscountPrice,costtotal,costprice,price,total,'; sqlz:=sqlz+'taxprice,taxTotal,date,usedtype,period,'; sqlz:=sqlz+'tax_total,discounttotal,vchtype,unit,'; sqlz:=sqlz+'ppath,bpath,kpath,epath,dpath,apath'; sqlz:=sqlz+') values ('; sqlz:=sqlz+'cast('''+newVchCode+''' as numeric),'''+kmid+''',cast('''+khid+''' as int),'; sqlz:=sqlz+'cast('''+empid+''' as int),cast('''+ckid+''' as int),cast('''+ListView1.Items.AppearanceItem[I].Data['Text9'].AsString+''' as int),'; sqlz:=sqlz+'cast('''+FormatFloat('0.00',0-strtofloat(ListView1.Items.AppearanceItem[I].Data['Text4'].AsString)*StrToFloat(unithuansuan))+''' as numeric(18,4)),cast('''+Edit7.Text+''' as numeric(18,4)),'; sqlz:=sqlz+'cast('''+ListView1.Items.AppearanceItem[I].Data['Text7'].AsString+''' as numeric(18,4))*cast('''+Edit7.Text+''' as numeric(18,4)),cast('''+cbje+''' as numeric(18,4)),cast('''+cbdj+''' as numeric(18,4)),'; sqlz:=sqlz+'cast('''+FormatFloat('0.00',StrtoFloat(ListView1.Items.AppearanceItem[I].Data['Text7'].AsString) / StrToFloat(unithuansuan))+''' as numeric(18,4)),'; sqlz:=sqlz+'cast('''+FormatFloat('0.00',0-(strtofloat(ListView1.Items.AppearanceItem[I].Data['Text4'].AsString)*strtofloat(ListView1.Items.AppearanceItem[I].Data['Text7'].AsString)))+''' as numeric(18,4)),'; sqlz:=sqlz+'cast('''+ListView1.Items.AppearanceItem[I].Data['Text7'].AsString+''' as numeric(18,4))*cast('''+Edit7.Text+''' as numeric(18,4)),cast('''+ling+''' as int),'''+FormatDateTime('YYYY-MM-DD',DateEdit1.Date)+''',cast('''+yi+''' as numeric),cast('''+period+''' as numeric),'; sqlz:=sqlz+'cast('''+FormatFloat('0.00',0-(strtofloat(ListView1.Items.AppearanceItem[I].Data['Text4'].AsString)*strtofloat(ListView1.Items.AppearanceItem[I].Data['Text7'].AsString)*strtofloat(Edit7.Text)))+''' as numeric(18,4)),'; sqlz:=sqlz+'cast('''+FormatFloat('0.00',0-(strtofloat(ListView1.Items.AppearanceItem[I].Data['Text4'].AsString)*strtofloat(ListView1.Items.AppearanceItem[I].Data['Text7'].AsString)*strtofloat(Edit7.Text)))+''' as numeric(18,4)),'; sqlz:=sqlz+'cast('''+vchtype+''' as numeric),cast('''+unitindex+''' as numeric),'; sqlz:=sqlz+''''+ppath+''','''+bpath+''','''+kpath+''','''+epath+''','''+dpath+''','''+apath+''') '; // showmessage(sqlz); ClientModule1.ClientDataSet1.Close; ClientModule1.ClientDataSet1.CommandText:=sqlz; ClientModule1.ClientDataSet1.Execute; // showmessage('第 '+inttostr(I)+' 执行完毕'); except On E:Exception do showmessage(e.Message); end;
end; except On E:Exception do showmessage(e.Message);
Please, @sxfgf, don't do this! This code is indecipherable!!! It's horrible!!!
try to organize each task more legibly and logically!!!
I think you could use a "Master/Detail" style here, as you are querying many tables in the database to find the desired values... so think about using "Store Procedure" or "View" to make your work easier.. .
Study about SQL "Union", "Join", "Master/Detail", "Stored Procedure", "View", etc...
Don't mix "multi-threaded" tasks with something "does everything"!!! It's not like this.
Do not mix "thread" tasks with screen visualization tasks. Do not mix database tasks with "thread", be cautious in this part... any error and the "thread" freezes or crashes the application!!!
Try to modularize your procedures! Do not create such long procedures... always try to keep a minimum of lines per task in the procedure!!! something around 20 lines maximum per procedure!!!
If you divide your "long task" into "small tasks", few lines, it becomes easier to maintain and understand the code!
此帖子包含附件: 大小:60.5K
----------------------------------------------
The higher the degree, the greater the respect given to the humblest!RAD 11.3
TClientdataset_Helper=class helper for TClientDataSet procedure DoQuery(Sql:string); end;
procedure TClientdataset_Helper.DoQuery(Sql:string); begin Close; CommandText:=Sql; Open; end;
TListView_Helper=class helper for TListView function ItemAsString(ItemIndex:integer;DataName:String):string; function ItemAsFloat(ItemIndex:integer;DataName:String):Double; end;
function TListView_Helper.ItemAsString(ItemIndex:integer;DataName:String):string; begin result:=Items.AppearanceItem[ItemIndex].Data[DataName].AsString; end;
function TListView_Helper.ItemAsDouble(ItemIndex:integer;DataName:String):Double; begin result:=StrToFloat(ItemAsString(ItemIndex,DataName)); end;
----------------------------------------------
z@S7
take all the values in the ListView and store them in a variable, so you avoid having to work with the screen (visual components);
Then, pass this variable to your "thread". This way, you avoid having to access the ListView all the time... a part can be solved this way!
type TMyProductData = record Id: integer; ItemsTotal: integer; Price: double; // currency... end;
procedure TForm1.Button1Click(Sender: TObject); var MyProductData : TMyProductData; MyListProductData: TArray<TMyProductData>; // NO NEEDS create TList, etc.. begin // store all values in my list... for var i := 0 to (ListView1.Items.Count - 1) do begin MyProductData.Id := 0; // the values in each ListView1 item.... MyProductData.ItemsTotal := 0; MyProductData.Price := 0; // MyListProductData := MyListProductData + [MyProductData]; end; // // ListView1 it's free for another actions, now!!! // // now you can call your thread passing the "MyListProductData" with all data from ListView1 // // RunMyThread( MyListProductData ); end;
----------------------------------------------
The higher the degree, the greater the respect given to the humblest!RAD 11.3
The "INSERT" part in the table, I think you should think better about how to do it!!!
If an error occurs in the "thread", the "INSERT" can fail at any point in the task... So, you should think better at this point!
When you work with "database", you always have to "start" and "end" a transaction:
procedure xxx; begin // // Always verify if exists a transaction opened... // if not DBxxxx._IS_NOT_IN_TRANSACTION then DBxxxx._START_A_TRANSACTION_HERE; // try try // insert, update, delete tasks ... // // ex: for var MyData in MyListProductData do begin MyTable.InsertXXXX(........ ); // or MyTable.UpdateXXXX(........ ); // or MyTable.DeleteXXXX(........ ); end; // // // // if all "inserts", "updates" or "deletes" = OK ... then "commit" DBxxxxx.COMMIT; // = SAVE ON DB, AND "END" THE TRANSACTION!!! = OK!!! except // WHAT TO DO IF SOME EXCEPTION ???? end; finally DBxxxx._ROLLBACK_IF_ANY_ERROR_ABOVE; // // etc... close table, or others actions end; end;
----------------------------------------------
The higher the degree, the greater the respect given to the humblest!RAD 11.3
First, let's evaluate the size of the "parameter" to be passed to the "Stored Procedure"... if it's too big, then, I think it won't be very easy... if it's small (few items), then, I I think you'll be able to pass without any problems!
A "Stored Procedure" is like a "Procedure" in Delphi, however, it uses the PSQL language of the database! You can use a "Stored Procedure" as you use a "Table", that is, you can use the "SP" as a data source (table), ex: "Select * from MyStoredProcedureXXX where FieldX = 1" etc... etc...
So, if the amount of parameters is not too big, you could use a "Stored Procedure" in the same way that you use a "Table" in the SQL component (ex. TFDQuery, etc...)
If the data you need to use is already in the database (in a table), then you can create your "Stored Procedure" using "select ...", "For Select ....", and all SQL commands to create your end result...
----------------------------------------------
The higher the degree, the greater the respect given to the humblest!RAD 11.3
SET @maincmd = ''; SET @columnname = ''; SET @columnlist = ''; SET @nickname = '';
DECLARE CUR_COLUMNLIST CURSOR FAST_FORWARD FOR SELECT columnname , nickname FROM dbo.v_userwise_columns WHERE userid = @userid
OPEN CUR_COLUMNLIST IF @@ERROR <> 0 BEGIN ROLLBACK RETURN END
FETCH NEXT FROM CUR_COLUMNLIST INTO @columnname, @nickname
WHILE @@FETCH_STATUS = 0 BEGIN SET @columnlist = @columnlist + @columnname + ','
FETCH NEXT FROM CUR_COLUMNLIST INTO @columnname, @nickname END CLOSE CUR_COLUMNLIST DEALLOCATE CUR_COLUMNLIST
IF NOT EXISTS (SELECT * FROM sys.views WHERE name = 'v_userwise_columns_value') BEGIN SET @maincmd = 'CREATE VIEW dbo.v_userwise_columns_value AS SELECT sjoid, CONVERT(BIGINT, ' + CONVERT(VARCHAR(10), @userid) + ') as userid , ' + CHAR(39) + @nickname + CHAR(39) + ' as nickname, ' + @columnlist + ' compcode FROM dbo.SJOTran ' END ELSE BEGIN SET @maincmd = 'ALTER VIEW dbo.v_userwise_columns_value AS SELECT sjoid, CONVERT(BIGINT, ' + CONVERT(VARCHAR(10), @userid) + ') as userid , ' + CHAR(39) + @nickname + CHAR(39) + ' as nickname, ' + @columnlist + ' compcode FROM dbo.SJOTran ' END
EXECUTE sp_executesql @maincmd END
---------- How call in your code, for example:
SELECT * FROM dbo.v_userwise_columns_value
----------------------------------------------
The higher the degree, the greater the respect given to the humblest!RAD 11.3