多线程:为甚么不执行????(50分)

  • 主题发起人 主题发起人 小邱
  • 开始时间 开始时间

小邱

Unregistered / Unconfirmed
GUEST, unregistred user!
unit U_TelRegThreed;
interface
uses
Classes,ExtCtrls,Dialogs,SysUtils,U_TelReg;
type
TConnect = class(TThread)
private
{ Private declarations }
fHosId,fDocId,fUserId:string;
fBalance,fTime,fRate:double;
//i:integer;
fTimer:TTimer;
procedure Timers(Sender:TObject);
procedure AccountTime();
protected
procedure Execute;
override;
public
constructor Create(Suspended:Boolean;HosId,DocId,UserId:string;Balance,Time,Rate:double);
end;
var
i:integer=0;
implementation
procedure TConnect.Timers(Sender:TObject);
begin
i:=i+1;
FTelReg.SB.Panels[0].Text :='预计:'+floattostr(fTime)+' 分钟';
FTelReg.SB.Panels[1].Text :='开始时间:'+Timetostr(Time);
FTelReg.SB.Panels[2].Text :='计时:'+floattostr(i)+' 分钟';
FTelReg.SB.Panels[3].Text :='状态:通话中……';
end;
procedure TConnect.AccountTime();
begin
fTimer:=TTimer.create(nil);
fTimer.Interval :=1000;
fTimer.OnTimer :=Timers;
end;
constructor TConnect.Create(Suspended:Boolean;HosId,DocId,UserId:string;Balance,Time,Rate:double);
begin
inherited Create(Suspended);
fHosId:=HosId;
fDocId:=DocId;
fUserId:=UserId;
fBalance:=Balance;
fTime:=Time;
fRate:=Rate;
FreeOnTerminate:=True;
end;
procedure TConnect.Execute;
begin
AccountTime();
end;

procedure TFTelReg.BitBtn1Click(Sender: TObject);
begin
inherited;
TConnect.Create(false,'102','0301','3518600029',156,48.75,3.2);
end;

为甚不执行procedure TConnect.Timers(Sender:TObject);???
 
这个很简单:你的线程刚CREATE不到半秒钟就退出FREE掉了,而且线程可能需要建立消息
循环来处理TIMER消息。
procedure TConnect.Execute;
begin
//线程开始执行
AccountTime();
//这一句大约只需要0.01秒
end;
//好,执行完了,线程FREE了 :(
另:TIMER一般只在主线程中使用,副线程就不需要了,你的代码可改为:
procedure TConnect.AccountTime();
begin
while not Terminateddo
begin
Sleep(1000);
Timers(Self);
end;
end;
这样就简单了。
 
to Huzzz:
unit U_TelRegThreed;
interface
uses
Classes,ExtCtrls,Dialogs,SysUtils,U_TelReg,U_OnLine,Forms;
type
TConnect = class(TThread)
private
{ Private declarations }
fHosId,fDocId,fUserId:string;
fBalance,fTime,fRate:double;
i:integer;
procedure Timers(Sender:TObject);
protected
procedure Execute;
override;
public
aForm: TFTelReg;
constructor Create(Suspended:Boolean;HosId,DocId,UserId:string;Balance,Time,Rate:double);
end;
implementation
procedure TConnect.Timers(Sender:TObject);
begin
i:=i+1;
aForm.SB.Panels[0].Text :='预计:'+floattostr(fTime)+' 分钟';
aForm.SB.Panels[1].Text :='开始时间:'+Timetostr(Time);
aForm.SB.Panels[2].Text :='计时:'+floattostr(i)+' 秒';
aForm.SB.Panels[3].Text :='状态:通话中……';
end;
constructor TConnect.Create(Suspended:Boolean;HosId,DocId,UserId:string;Balance,Time,Rate:double);
begin
inherited Create(Suspended);
fHosId:=HosId;
fDocId:=DocId;
fUserId:=UserId;
fBalance:=Balance;
fTime:=Time;
fRate:=Rate;
FreeOnTerminate:=True;
aForm := TFTelReg.Create(Application);
aForm.Show;
end;
procedure TConnect.Execute;
begin
i:=0;
while not Terminateddo
begin
Sleep(1000);
Timers(Self);
end;
end;
end.

procedure TFOnLine.bbCreateClick(Sender: TObject);
begin
TConnect.Create(false,'102','0301','3518600029',156,48.75,3.2);
end
这样在线程中动态创建窗体,线程安全么??
对了,还有一个,当我把FTelReg窗体关闭(线程还在执行),会出Access Violation错。光标
指向 aForm.SB.Panels[0].Text :='预计:'+floattostr(fTime)+' 分钟';
要在关闭FTelReg前中止线程!!该如何??我用TCnnect.Terminated出错:未声明标识符
注:两个窗体:FOnLine,FTelReg
一个Uuit:UTelRegThreed
 
有可能生成多个动态FTelReg窗体!!!
 
你的线程拥有者是谁?
 
是由窗体FOnLine的按钮激发的。
 
想在关闭窗体的时候杀掉线程?简单啊,1是为了保证数据的安全性可以先让线程自己终止,
到一定时间检测该线程是否已经退了,如果没有退就强杀;2就是直接强杀;做法如下:
方法1:
取得你的线程的句柄,用API函数WaitForSingleObject(线程句柄,等待的最大时间);再
根据该函数的返回值来确定线程是否退出,如果为WAIT_TIMEOU,则表明线程退出等待超时,
你可以在这个函数 后面使用TerminateThread(线程句柄,线程退出码)函数强杀线程;
其中的“线程退出码”为你自己指定的任意DWORD值;
方法2:
就是上面说到的直接用TerminateThread(线程句柄,线程退出码)函数强杀线程;
 
>>这样在线程中动态创建窗体,线程安全么??
你的窗体是在创建线程时创建的,因此实际上是由主线程创建的,并不是TConnect。
>>对了,还有一个,当我把FTelReg窗体关闭(线程还在执行),会出Access Violation错。光标
>>指向 aForm.SB.Panels[0].Text :='预计:'+floattostr(fTime)+' 分钟';
线程中不能直接访问主线程使用的VCL,因此你的代码应为
procedure TConnect.Timers;//把参数(Sender:TObject)去掉
...
procedure TConnect.Execute;
begin
i:=0;
while not Terminateddo
begin
Sleep(1000);
Synchronize(Timers);//同步调用
end;
end;

>>要在关闭FTelReg前中止线程!!该如何??
因为窗体是在线程创建时创建的,因此应该在线程释放时FREE;我建议你关闭FTelReg之后
不要FREE(把Action=caFree一句去掉),而是在线程FREE时进行:
procedure TConnect.Destory;
begin
if Assigned(FTelReg) then
FreeAndNil(FTelReg);
inherited;
end;
procedure TConnect.Timers(Sender:TObject);
begin
if not Assigned(FTelReg) then
//这样保证FTelReg在FREE之后不再执行
Exit;
i:=i+1;
aForm.SB.Panels[0].Text :='预计:'+floattostr(fTime)+' 分钟';
aForm.SB.Panels[1].Text :='开始时间:'+Timetostr(Time);
aForm.SB.Panels[2].Text :='计时:'+floattostr(i)+' 秒';
aForm.SB.Panels[3].Text :='状态:通话中……';
end;
 
to huzzz:
procedure TConnect.Destory;
begin
if Assigned(FTelReg) then
//这里的FTelReg应该为aForm吧???
FreeAndNil(FTelReg);
inherited;
end;
procedure TConnect.Timers(Sender:TObject);
begin
if not Assigned(FTelReg) then
//这样保证FTelReg在FREE之后不再执行
//这里的FTelReg也应该为aForm吧???
因为FTelReg在:
program P_Main;
begin
Application.Initialize;
Application.Title := '经济界';
Application.CreateForm(Tdm, dm);
Application.CreateForm(TMainForm, MainForm);
Application.CreateForm(TFTelReg, FTelReg);
Application.Run;
end.
就已经创建,在线程中动态显示是作为一个模板,根据多个用户(动态显示多个窗体),显示不同用户的信息。

 
多人接受答案了。
 
后退
顶部