我的线程为什么执行了一会就停掉了,哪位大狭可以看看我的代码?(6分)

  • 主题发起人 delphiboy
  • 开始时间
D

delphiboy

Unregistered / Unconfirmed
GUEST, unregistred user!
ProgressBar2: TProgressBar;
sqy: TADOQuery;
procedure FormKeyDown(Sender: TObject;
var Key: Word;
Shift: TShiftState);
procedure Timer1Timer(Sender: TObject);
procedure FormCreate(Sender: TObject);
procedure Button1Click(Sender: TObject);
private
{ Private declarations }
public
ThreadRuning:Boolean;
{ Public declarations }
end;

type
Tdatatranthread=class(tthread)
private
SadoQuery :TadoQuery ;
DadoQuery :TadoQuery ;
SSQLStr,DSQLStr:string;
KeyName:array of string;
sser,dser,sdb,ddb,stb,dtb,succ,ops:string;
sstr ,dstr ,sdate:string;
protected
procedure SCloseData;
procedure SOpenData;
procedure DCloseData;
proceduredo
penData;
procedure AppendToDest(keyfieldname ,fieldtimename :string);
Procedure ClearAndCopyToDest;
procedure ClearDestData;
procedure GetTagYes(sdateb :tdatetime;inc :integer);
procedure GetTagNo(sdateb :tdatetime ;inc :integer);
public
procedure execute ;override ;
constructor create;
end;
var
Form1: TForm1;
implementation
uses ut_dm ;
{$R *.dfm}
procedure TForm1.FormKeyDown(Sender: TObject;
var Key: Word;
Shift: TShiftState);
begin
if key=vk_return then
perform(WM_NEXTDLGCTL ,0,0);
end;

procedure TForm1.Timer1Timer(Sender: TObject);
begin
if (not ThreadRuning) and (Sqy.RecordCount>0) then
begin
//调用线程
ThreadRuning:=True;
TDataTranThread.create;
end;

end;

procedure TForm1.FormCreate(Sender: TObject);
var cons :string;
begin
ThreadRuning:=False;
cons :='FILE NAME='+extractfilepath(application.Name)+'td_m.udl';
sqy.ConnectionString:=cons;
sqy.SQL.Clear;
sqy.SQL.Add('select * from traninf');
sqy.Open;
if SQY.RecordCount<=0 then
begin
application.Terminate;
exit;
end;
end;

{ Tdatatranthread }
constructor Tdatatranthread.create;
begin
inherited create(true) ;
freeonterminate :=true ;
SAdoQuery :=TadoQuery.Create(form1);
DAdoQuery :=tadoQuery.Create(form1);
Resume;
end;


procedure Tdatatranthread.execute;
var tpstr:string;
KeyTempStr:String;
TimeFieldName,tps:string;
sdateb:string ;
begin
tpstr :=datetimetostr(now);
form1.ProgressBar1.Max:=form1.sqy.RecordCount;
form1.Sqy.First;
//配置表
form1.ProgressBar1.Min:=0;
form1.ProgressBar1.Position:=0;
form1.ProgressBar1.Step:=1;
while not form1.Sqy.Eofdo
begin
form1.sqy.Edit;
form1.sqy.FieldByName('succ').AsString:='RUN';
form1.sqy.Post;
ops:=UpperCase(trim(form1.Sqy.FieldByName('optstr').AsString)) ;
sser:=form1.Sqy.FieldByName('ser_name').AsString ;
//数据源服务器名称
sdb :=form1.Sqy.FieldByName('sdb_name').AsString ;
//数据源数据库名称
stb :=form1.Sqy.FieldByName('stb_name').AsString ;
//数据源数据表名称
dser:=form1.Sqy.FieldByName('dser_name').AsString ;//目的服务器名称
ddb :=form1.Sqy.FieldByName('ddb_name').AsString ;
//目的数据库名称
dtb :=form1.Sqy.FieldByName('dtb_name').AsString ;
//目的表名称
succ:=form1.Sqy.FieldByName('succ').AsString ;
//更新成功标记
sdateb :=trim(form1.Sqy.FieldByName('optdate').AsString) ;
//执行操作时间
KeyTempStr:=form1.Sqy.fieldByName('KeyFieldName').AsString;
//使用的主键值
TimeFieldName:=form1.Sqy.fieldByName('UpTimeFieldName').AsString;//使用时间字段的名称
//读到KeyName中
Synchronize(SCloseData);
Synchronize(DCloseData);
sdate:=FormatDateTime('yyyymmdd',Now);
//1,数据库名称,2,服务器的名称,3,本地电脑名称
sstr :=' Provider=SQLOLEDB.1;Integrated Security=SSPI;Persist Security Info=False;'
+' Initial Catalog='+sdb+';Data Source='+sser;
dstr :=' Provider=SQLOLEDB.1;Integrated Security=SSPI;Persist Security Info=False;'
+' Initial Catalog='+ddb+';Data Source='+dser;
dadoQuery.ConnectionString :=dstr ;
sadoQuery.ConnectionString :=sstr ;
if ops='A' then
//修改,添加
begin
//begin
ops 'A'
try
//取源表更新的时间比这次要执行的时间大的数据,
SSQLStr:=' select * from '+stb+' where '+TimeFieldName+'>'+#39+formatDateTime('yyyymmdd HH:NN:SS',strtodatetime(sdateb))+#39+'Order by '+TimeFieldName+' Desc';
//用主线程打开源数据
Synchronize(SOpenData);
SadoQuery.First;
form1.sqy.Edit;
// form1.sqy.FieldByName('optdate').AsDateTime:=strtodatetime(SadoQuery.FieldByName(TimeFieldName).AsString);
if length(trim(SAdoQuery.FieldByName(TimeFieldName).AsString))>8 then
form1.sqy.FieldByName('optdate').AsString :=formatdatetime('YYYY-MM-DD HH:NN:SS',strtodatetime(SadoQuery.FieldByName(TimeFieldName).AsString))
else
begin
tps:=copy(SadoQuery.FieldByName(TimeFieldName).AsString,1,4)+'-'+copy(SadoQuery.FieldByName(TimeFieldName).AsString,5,2)+'-'+copy(SadoQuery.FieldByName(TimeFieldName).AsString,7,2) ;
form1.sqy.FieldByName('optdate').AsString :=formatdatetime('YYYY-MM-DD HH:NN:SS',strtodatetime(tps));
end;
form1.sqy.Post;
//执行A操作
AppendToDest(KeyTempStr,timefieldname );
except
end;
end
else
if ops='B' then
begin
try
SSQLStr:='select * from '+stb;
Synchronize(SOpenData);
ClearAndCopyToDest;
except
end;
end;
form1.ProgressBar1.StepIt;
form1.sqy.Edit;
form1.sqy.FieldByName('succ').AsString:='OK';
form1.sqy.Post;
form1.sqy.Next;
end;
form1.ThreadRuning:=False;
end;


end.

 
我也正在写线程的东东,学习中。。。关注
 
一般的线程函数都有一个 while not terminaledo
begin
end;
terminale 我不知道有没有写错,反正是个线程的属性
 
程序执行完了没?
 
execute;
里的ADO的东西要初始化,而且我建议你所有的ADOQuery都在execute里创建
 
几点建议, 是我写多线程应用的一些心得:
1. 在构造函数中创建的对象最后应该在析构函数中释放.
2. 在Execute里的循环应该检查Terminated是否为真, 是则应该终止执行.
3. 尽量不要在线程中调用外部变量,比如你的代码里的form1.ThreadRuning:=False, 取代的方法是处理OnTerminate事件或者在析构函数中向调用者发送消息, 通知调用者该线程已经结束.比如使用PostMessage函数. 确实需要访问外部变量, 则应小心处理共享冲突, 比如可以使用互斥量. 应该保证同时只有一个线程在进行写操作.
4. 对应界面控件的处理应该回到主线程中, 比如处理进度条时, 应该写一个内部函数, 然后用同步方法调用. 相反, 我不知道你的SOpenData方法是做什么的,如果不是更新界面的操作,则不需要同步调用,使用互知量就可以了. 对于可以锁定访问的元件, 应该先锁定,然后更新,最后释放锁定.
 
顶部