线程编程时,我写了一个线程程序,在运行时没有问题,但程序结束后,说句柄无效, ( 积分: 30 )

  • 主题发起人 willing66
  • 开始时间
W

willing66

Unregistered / Unconfirmed
GUEST, unregistred user!
线程编程时,我写了一个线程程序,在运行时没有问题,但程序结束后,说句柄无效,
我是先定义一个线程类,
在button的单击事件中创建一个线程来执行查询任务,代码结构如下:
单击事件是这样写:
th:=myThread.create(True;
sqlstr);
th.freeonTerminate:=True;
th.resume

线程的定义是:
myThread=class(TThread)
private
sqlstr: string
protected
procedure create()
procedure Execute;
end;

大概是这样吧,在程序运行时没有错,要程序结束时,说句柄无效.
 
线程编程时,我写了一个线程程序,在运行时没有问题,但程序结束后,说句柄无效,
我是先定义一个线程类,
在button的单击事件中创建一个线程来执行查询任务,代码结构如下:
单击事件是这样写:
th:=myThread.create(True;
sqlstr);
th.freeonTerminate:=True;
th.resume

线程的定义是:
myThread=class(TThread)
private
sqlstr: string
protected
procedure create()
procedure Execute;
end;

大概是这样吧,在程序运行时没有错,要程序结束时,说句柄无效.
 
在你的构照器(create)下写:
inherited Create(False);
好象以前我见过这个问题
 
inherited Create(False);
这个在线程的create事件过程中写了.
 
是否终止线程时未释放占用的资源或是要释放的资源不存在?
 
procedure create()改为
constructor create(B:Boolean;s : String);

constructor create(B:Boolean;s : String);
begin
sqlStr := s;
freeonTerminate := True;
inherited Create(b);
end;
 
unit Uthread;
interface
uses
Classes, Ufrm_Selection, SysUtils, ExtCtrls, ComCtrls;
type
TSelectFac = class(TThread)
private
{ Private declarations }
Fpnltext: TStatusBar;
protected
procedure Execute;
override;
public
constructor Create(stspnl: TStatusBar;
bool: boolean);
end;

implementation

procedure TSelectFac.Execute;
begin
{ Place thread code here }
FrmSelect.Facquery.Close;
FrmSelect.Facquery.SQL.Clear;
FrmSelect.Facquery.SQL.Add(selFacSQL);
FrmSelect.Facquery.Open;
// FpnlText.Panels[0].text :=IntToStr(FrmSelect.Facquery.RecordCount)+'条记录';
// FpnlText.Panels[1].Text :='完成';
exit;
// FrmSelect.statusbar2.Panels[1].Text :='完成';
// FrmSelect.statusbar2.Panels[0].Text :=IntToStr(FrmSelect.Facquery.RecordCount)+'条记录';
end;

constructor TSelectFac.Create(stspnl: TStatusBar;
bool: boolean);
begin
FpnlText :=stspnl;
inherited create(bool);
end;

unit Ufrm_selection;
interface
uses
Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms,
Dialogs, cxStyles, cxCustomData, cxGraphics, cxFilter, cxData,
cxDataStorage, cxEdit, DB, cxDBData, cxLookAndFeelPainters, cxMaskEdit,
cxDropDownEdit, StdCtrls, cxButtons, cxTextEdit, cxContainer, cxLabel,
ComCtrls, cxGridLevel, cxGridCustomTableView, cxGridTableView,
cxGridDBTableView, cxClasses, cxControls, cxGridCustomView, cxGrid,
ExtCtrls, cxPC, ADODB, BusinessSkinForm;
type
TFrmSelect = class(TForm)
SelConnection: TADOConnection;
FDataSource: TDataSource;
bsBusinessSkinForm1: TbsBusinessSkinForm;
Itemquery: TADOQuery;
Facquery: TADOQuery;
MtDataSource: TDataSource;
FTYPCorquery: TADOQuery;
UpdateQuery: TADOQuery;
FTYPCorDataSource: TDataSource;
MtTYPCorQuery: TADOQuery;
MtTYPCorDataSource: TDataSource;
cxPageControl1: TcxPageControl;
cxTabSheet1: TcxTabSheet;
Splitter2: TSplitter;
Panel4: TPanel;
cxGrid1: TcxGrid;
cxGrid1DBTableView1: TcxGridDBTableView;
cxGrid1DBTableView1DBColumn1: TcxGridDBColumn;
cxGrid1DBTableView1DBColumn2: TcxGridDBColumn;
cxGrid1DBTableView1DBColumn3: TcxGridDBColumn;
cxGrid1DBTableView1DBColumn4: TcxGridDBColumn;
cxGrid1DBTableView1DBColumn5: TcxGridDBColumn;
cxGrid1DBTableView1DBColumn6: TcxGridDBColumn;
cxGrid1DBTableView1DBColumn7: TcxGridDBColumn;
cxGrid1Level1: TcxGridLevel;
StatusBar2: TStatusBar;
Panel5: TPanel;
Panel6: TPanel;
GroupBox2: TGroupBox;
cxLabel4: TcxLabel;
cxTextEdit3: TcxTextEdit;
cxTextEdit4: TcxTextEdit;
cxLabel5: TcxLabel;
cxLabel6: TcxLabel;
cxButton3: TcxButton;
cxButton4: TcxButton;
cxComboBox2: TcxComboBox;
Panel7: TPanel;
cxButton5: TcxButton;
cxLabel7: TcxLabel;
cxTextEdit5: TcxTextEdit;
cxTabSheet2: TcxTabSheet;
Splitter1: TSplitter;
Panel1: TPanel;
Panel3: TPanel;
GroupBox1: TGroupBox;
cxTextEdit1: TcxTextEdit;
cxLabel1: TcxLabel;
cxTextEdit2: TcxTextEdit;
cxLabel2: TcxLabel;
cxLabel3: TcxLabel;
cxButton1: TcxButton;
cxButton2: TcxButton;
cxComboBox1: TcxComboBox;
Panel2: TPanel;
cxGrid2: TcxGrid;
cxGrid2DBTableView1: TcxGridDBTableView;
cxGrid2DBTableView1DBColumn1: TcxGridDBColumn;
cxGrid2DBTableView1DBColumn2: TcxGridDBColumn;
cxGrid2DBTableView1DBColumn3: TcxGridDBColumn;
cxGrid2DBTableView1DBColumn4: TcxGridDBColumn;
cxGrid2DBTableView1DBColumn5: TcxGridDBColumn;
cxGrid2DBTableView1DBColumn6: TcxGridDBColumn;
cxGrid2DBTableView1DBColumn7: TcxGridDBColumn;
cxGrid2Level1: TcxGridLevel;
StatusBar1: TStatusBar;
Panel8: TPanel;
cxButton6: TcxButton;
cxButton7: TcxButton;
procedure cxButton3Click(Sender: TObject);
procedure cxButton1Click(Sender: TObject);
procedure FormShow(Sender: TObject);
procedure cxButton4Click(Sender: TObject);
procedure cxButton2Click(Sender: TObject);
procedure cxButton5Click(Sender: TObject);
procedure FormClose(Sender: TObject;
var Action: TCloseAction);
private
{ Private declarations }
selFnumber: string;
selFName: string;
selFTYPCor: string;
procedure ThreadDone(Sender: TObject);
public
{ Public declarations }
procedure SelFacTerminate;
end;

implementation
uses
Uthread;
procedure TFrmSelect.cxButton3Click(Sender: TObject);
var
strSQL: widestring;
begin
statusbar2.Panels[1].Text :='请稍后,系统进行处理.......';
selFnumber :=trim(cxTextEdit3.Text);
selFname :=trim(cxTextEdit4.Text);
selFTYPCor :=trim(cxComboBox2.Text);
strSQL :='SELECT DISTINCT FitemId, Fnumber, FName, Ftax, TYPCor FROM CPSup WHERE ';
if selFnumber <> '' then
strSQL := strSQL + ' Fnumber LIKE ' + '''%' + selFnumber + '%''' + ' AND';
if selFName <> '' then
strSQL := strSQL + ' FName LIKE ' + '''%' + selFname + '%''' + ' AND';
if selFTYPCor <> '' then
strSQL := strSQL + ' TYPCor LIKE ' + '''%' + selFTYPCor + '%''' + ' AND';
strSQL := Copy( strSQL, 1, Length(strSQL)- 4);
strSQL :=trim(strSQL);
SelFacSQL :=strSQL;
ThSelFac:= TSelectFac.Create(StatusBar2, False);
ThSelFac.FreeOnTerminate :=True;
// ThSelFac.OnTerminate:= SelFacTerminate ;
ThSelFac.OnTerminate :=ThreadDone;
ThSelFac.Resume;

{
FacQuery.Close;
FacQuery.SQL.Clear;
FacQuery.SQL.Add(strSQL);
FacQuery.Open;
}
{
if FacQuery.RecordCount =0 then
showmessage('没的找到您要的数据!');
StatusBar2.Panels[0].Text := IntToStr(FacQuery.RecordCount) + '条记录';
}
end;

代码的内容是这样的,不是用线程去实现的话就可以正常,如果用线程来实现就会在线程结束时说句柄无效。
我经常写别的程序时,也会去这样的错,只要用到线程就会出现这样的错。
真希望有人能够帮我解决这问题。
 
好奇怪的语句:
constructor TSelectFac.Create(stspnl: TStatusBar;
bool: boolean);
begin
FpnlText :=stspnl;
inherited create(bool);
end;

ThSelFac:= TSelectFac.Create(StatusBar2, False);
// 这是要线程对象创建后立即执行
ThSelFac.FreeOnTerminate :=True;
// ThSelFac.OnTerminate:= SelFacTerminate ;
ThSelFac.OnTerminate :=ThreadDone;
ThSelFac.Resume;
// 这里又Resume是什么意思呢?
ThreadDone代码呢?SelFacTerminate又是做什么的东东?
 
我把ThSelFac:= TSelectFac.Create(StatusBar2, False);这里的改为True时,也不行.
// ThSelFac.OnTerminate:= SelFacTerminate ;这个已经注释了.
就是不行
 
你在线程使用ADO控件,要用CoInitialize进行初始化,并且在线程中访问主线程的各个控件要用Synchronize进行访问.
 
我想不是这个原因,因为我只有在程序结束才出这样的错,其它时候都可以正确运行。我以前有看过这样的程序,也是用到了其它控件,但是不是出错的。
 
ThreadDone这个方法的代码是什么?
你说线程结束的时候才会报错,那很有可能出错就是在ThreadDone这个方法中.
 
我有加这段代码时会出错,没加时也出错。
这个里的代码就是要线程变量 th:=nil;
没有做其它事情。
 
照上面这样说,实在是看不出有什么问题了。
你可以试试将线程中execute方法中的语句全部去掉,留个空的execute方法,在执行你的程序看看是否有报错。
 
试试再说
 
我原来程序的错误是这样的,
Project Prj_thread.exe raised exception class EOSError with message ‘System Error. Code: 5. 拒绝访问。’. Process stopped. Use Step or Run to continue.
我写的一个简单程序如下,这个程序却没有错,但是如果Button1连续点了几个就会出同样的错误。
unit ThreadFrm;
interface
uses
Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms,
Dialogs, StdCtrls;
type
TForm1 = class(TForm)
Button1: TButton;
Memo1: TMemo;
Button2: TButton;
Edit1: TEdit;
procedure Button1Click(Sender: TObject);
procedure Button2Click(Sender: TObject);
private
{ Private declarations }
public
procedure threaddo(Sender: TObject);
{ Public declarations }
end;


var
Form1: TForm1;
implementation
uses
UTMyThread;
var
th: TMyThread;
//procedure threaddo();
//begin
// th:=nil;
//end;

{$R *.dfm}
procedure TForm1.Button1Click(Sender: TObject);
var
// th: TMyThread;
i: integer;
begin
Memo1.Lines.Clear;
th:=TMyThread.Create(true);
Th.FreeOnTerminate :=True;
// Th.OnTerminate :=threaddo;
th.Resume;
for i:=-2000 to 2000do
begin
//
end;
// Th.Terminate ;
end;

procedure TForm1.Button2Click(Sender: TObject);
begin

Th.Terminate;
Edit1.Text:=String(th);
end;

procedure TForm1.threaddo(Sender: TObject);
begin
th:=nil;
end;

end.


unit UTMyThread;
interface
uses
Classes, ThreadFrm, SysUtils;
type
TMyThread = class(TThread)
private
{ Private declarations }
protected
procedure Execute;
override;
end;

implementation
{ Important: Methods and properties of objects in visual components can only be
used in a method called using Synchronize, for example,
Synchronize(UpdateCaption);
and UpdateCaption could look like,
procedure TMyThread.UpdateCaption;
begin
Form1.Caption := 'Updated in a thread';
end;
}
{ TMyThread }
procedure TMyThread.Execute;
var
i: integer;
begin
{ Place thread code here }
i:=0;
while not Terminateddo
begin
inc(i);
Form1.Memo1.Lines.Add('Lines '+IntToStr(i));
if i=10000 then
i:=0;
end;
end;

end.
 
这样写也正确:
unit ThreadFrm;
interface
uses
Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms,
Dialogs, StdCtrls;
type
TForm1 = class(TForm)
Button1: TButton;
Memo1: TMemo;
Button2: TButton;
Edit1: TEdit;
procedure Button1Click(Sender: TObject);
procedure Button2Click(Sender: TObject);
private
{ Private declarations }
public
procedure threaddo(Sender: TObject);
{ Public declarations }
end;


var
Form1: TForm1;
implementation
uses
UTMyThread;
var
th: TMyThread;
//procedure threaddo();
//begin
// th:=nil;
//end;

{$R *.dfm}
procedure TForm1.Button1Click(Sender: TObject);
var
// th: TMyThread;
i: integer;
begin
Memo1.Lines.Clear;
th:=TMyThread.Create(true);
Th.FreeOnTerminate :=True;
Th.OnTerminate :=threaddo;
th.Resume;
for i:=-2000 to 2000do
begin
//
end;
// Th.Terminate ;
button1.Enabled:=False;
end;

procedure TForm1.Button2Click(Sender: TObject);
begin

Th.Terminate;
Edit1.Text:=String(th);
Button1.Enabled :=True;
end;

procedure TForm1.threaddo(Sender: TObject);
begin
Memo1.Lines.Add('Thread is over!');
th:=nil;
end;

end.


unit UTMyThread;
interface
uses
Classes, ThreadFrm, SysUtils;
type
TMyThread = class(TThread)
private
{ Private declarations }
protected
procedure Execute;
override;
end;

implementation
{ Important: Methods and properties of objects in visual components can only be
used in a method called using Synchronize, for example,
Synchronize(UpdateCaption);
and UpdateCaption could look like,
procedure TMyThread.UpdateCaption;
begin
Form1.Caption := 'Updated in a thread';
end;
}
{ TMyThread }
procedure TMyThread.Execute;
var
i: integer;
begin
{ Place thread code here }
i:=0;
while not Terminateddo
begin
inc(i);
Form1.Memo1.Lines.Add('Lines '+IntToStr(i));
if i=10000 then
i:=0;
end;
end;

end.
 
awfigsk
你能写一个用ADO控件,要用CoInitialize进行初始化,并且在线程中访问主线程的各个控件要用Synchronize进行访问。这样的程序的例子给我看一下好吗?
谢谢!
 
unit Uthread;
interface
uses
Classes, Ufrm_Selection, SysUtils, ExtCtrls, ComCtrls, ADODB;
type
TSelectFac = class(TThread)
private
{ Private declarations }
Fpnltext: TStatusBar;
fsqlstr:String;
protected
procedure Execute;
override;
public
constructor Create(stspnl: TStatusBar;
bool: boolean;
sqlstr:String);
end;

implementation

procedure TSelectFac.Execute;
var
Facquery:TADOQuery;
begin
{ Place thread code here }
try
Coinitialize(nil);
Facquery:=TADOQuery.create(nil);
Facquery.connectionstring:='..';
Facquery.SQL.Clear;
Facquery.SQL.Add(fSQLstr);
Facquery.Open;
Couninitialize;
exit;
except
...
end;
end;

constructor TSelectFac.Create(stspnl: TStatusBar;
bool: boolean;
Sqlstr:string;);
begin
inherited create(bool);
FpnlText :=stspnl;
fsqlstr:=sqlstr;
end;

unit Ufrm_selection;
interface
uses
Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms,
Dialogs, cxStyles, cxCustomData, cxGraphics, cxFilter, cxData,
cxDataStorage, cxEdit, DB, cxDBData, cxLookAndFeelPainters, cxMaskEdit,
cxDropDownEdit, StdCtrls, cxButtons, cxTextEdit, cxContainer, cxLabel,
ComCtrls, cxGridLevel, cxGridCustomTableView, cxGridTableView,
cxGridDBTableView, cxClasses, cxControls, cxGridCustomView, cxGrid,
ExtCtrls, cxPC, ADODB, BusinessSkinForm;
type
TFrmSelect = class(TForm)
SelConnection: TADOConnection;
FDataSource: TDataSource;
bsBusinessSkinForm1: TbsBusinessSkinForm;
Itemquery: TADOQuery;
Facquery: TADOQuery;
MtDataSource: TDataSource;
FTYPCorquery: TADOQuery;
UpdateQuery: TADOQuery;
FTYPCorDataSource: TDataSource;
MtTYPCorQuery: TADOQuery;
MtTYPCorDataSource: TDataSource;
cxPageControl1: TcxPageControl;
cxTabSheet1: TcxTabSheet;
Splitter2: TSplitter;
Panel4: TPanel;
cxGrid1: TcxGrid;
cxGrid1DBTableView1: TcxGridDBTableView;
cxGrid1DBTableView1DBColumn1: TcxGridDBColumn;
cxGrid1DBTableView1DBColumn2: TcxGridDBColumn;
cxGrid1DBTableView1DBColumn3: TcxGridDBColumn;
cxGrid1DBTableView1DBColumn4: TcxGridDBColumn;
cxGrid1DBTableView1DBColumn5: TcxGridDBColumn;
cxGrid1DBTableView1DBColumn6: TcxGridDBColumn;
cxGrid1DBTableView1DBColumn7: TcxGridDBColumn;
cxGrid1Level1: TcxGridLevel;
StatusBar2: TStatusBar;
Panel5: TPanel;
Panel6: TPanel;
GroupBox2: TGroupBox;
cxLabel4: TcxLabel;
cxTextEdit3: TcxTextEdit;
cxTextEdit4: TcxTextEdit;
cxLabel5: TcxLabel;
cxLabel6: TcxLabel;
cxButton3: TcxButton;
cxButton4: TcxButton;
cxComboBox2: TcxComboBox;
Panel7: TPanel;
cxButton5: TcxButton;
cxLabel7: TcxLabel;
cxTextEdit5: TcxTextEdit;
cxTabSheet2: TcxTabSheet;
Splitter1: TSplitter;
Panel1: TPanel;
Panel3: TPanel;
GroupBox1: TGroupBox;
cxTextEdit1: TcxTextEdit;
cxLabel1: TcxLabel;
cxTextEdit2: TcxTextEdit;
cxLabel2: TcxLabel;
cxLabel3: TcxLabel;
cxButton1: TcxButton;
cxButton2: TcxButton;
cxComboBox1: TcxComboBox;
Panel2: TPanel;
cxGrid2: TcxGrid;
cxGrid2DBTableView1: TcxGridDBTableView;
cxGrid2DBTableView1DBColumn1: TcxGridDBColumn;
cxGrid2DBTableView1DBColumn2: TcxGridDBColumn;
cxGrid2DBTableView1DBColumn3: TcxGridDBColumn;
cxGrid2DBTableView1DBColumn4: TcxGridDBColumn;
cxGrid2DBTableView1DBColumn5: TcxGridDBColumn;
cxGrid2DBTableView1DBColumn6: TcxGridDBColumn;
cxGrid2DBTableView1DBColumn7: TcxGridDBColumn;
cxGrid2Level1: TcxGridLevel;
StatusBar1: TStatusBar;
Panel8: TPanel;
cxButton6: TcxButton;
cxButton7: TcxButton;
procedure cxButton3Click(Sender: TObject);
procedure cxButton1Click(Sender: TObject);
procedure FormShow(Sender: TObject);
procedure cxButton4Click(Sender: TObject);
procedure cxButton2Click(Sender: TObject);
procedure cxButton5Click(Sender: TObject);
procedure FormClose(Sender: TObject;
var Action: TCloseAction);
private
{ Private declarations }
selFnumber: string;
selFName: string;
selFTYPCor: string;
procedure ThreadDone(Sender: TObject);
public
{ Public declarations }
procedure SelFacTerminate;
end;

implementation
uses
Uthread;
procedure TFrmSelect.cxButton3Click(Sender: TObject);
var
strSQL: widestring;
begin
statusbar2.Panels[1].Text :='请稍后,系统进行处理.......';
selFnumber :=trim(cxTextEdit3.Text);
selFname :=trim(cxTextEdit4.Text);
selFTYPCor :=trim(cxComboBox2.Text);
strSQL :='SELECT DISTINCT FitemId, Fnumber, FName, Ftax, TYPCor FROM CPSup WHERE ';
if selFnumber <> '' then
strSQL := strSQL + ' Fnumber LIKE ' + '''%' + selFnumber + '%''' + ' AND';
if selFName <> '' then
strSQL := strSQL + ' FName LIKE ' + '''%' + selFname + '%''' + ' AND';
if selFTYPCor <> '' then
strSQL := strSQL + ' TYPCor LIKE ' + '''%' + selFTYPCor + '%''' + ' AND';
strSQL := Copy( strSQL, 1, Length(strSQL)- 4);
strSQL :=trim(strSQL);
SelFacSQL :=strSQL;
ThSelFac:= TSelectFac.Create(StatusBar2, False,strsql);
ThSelFac.FreeOnTerminate :=True;
ThSelFac.OnTerminate :=ThreadDone;
ThSelFac.Resume;
end;

procedure TForm1.threaddo(Sender: TObject);
begin
th:=nil;
end;
 
awfigsk
我还想请教一下,Coinitialize函数在哪个单元中,我怎么从帮助文件中找一到这个函数。
谢谢
 

Similar threads

S
回复
0
查看
3K
SUNSTONE的Delphi笔记
S
S
回复
0
查看
2K
SUNSTONE的Delphi笔记
S
D
回复
0
查看
1K
DelphiTeacher的专栏
D
I
回复
0
查看
552
import
I
顶部