Delphi线程异常机制 [英] Delphi thread exception mechanism
问题描述
//线程代码
$ b $单位Unit2; b unit Unit2;
接口
使用
类,
对话框,
SysUtils,
StdCtrls;
type
TTest = class(TThread)
private
protected
j:Integer;
程序执行;覆盖
procedure setNr;
public
aBtn:tbutton;
结束
执行
{TTest}
程序TTest.Execute;
var
i:整数;
a:TStringList;
begin
//仅对某些操作进行操作
j:= 0;
for i:= 0到100000000 do
j:= j + 1;
for i:= 0到100000000 do
j:= j + 1;
for i:= 0到100000000 do
j:= j + 1;
for i:= 0到100000000 do
j:= j + 1;
for i:= 0到100000000 do
j:= j + 1;
for i:= 0 to 100000000 do
j:= j + 1;
for i:= 0到100000000 do
j:= j + 1;
for i:= 0到100000000 do
j:= j + 1;
同步(setnr);
a [2]:='dbwdbkbckbk' //这应该提高AV !!!!!!
end;
程序TTest.setNr;
begin
aBtn.Caption:= IntToStr(j)
end;
结束。
项目代码
code> unit Unit1;
接口
使用
Windows,消息,SysUtils,变体,类,图形,控件,表单,
对话框,
Unit2, StdCtrls;
type
TForm1 = class(TForm)
Button1:TButton;
procedure Button1Click(Sender:TObject);
procedure FormCreate(Sender:TObject);
private
public
nrthd:整数;
acrit:TRTLCriticalSection;
procedure bla();
procedure bla1();
函数bla2():boolean;
procedure onterm(Sender:TObject);
结束
var
Form1:TForm1;
执行
{$ R * .dfm}
程序TForm1.bla;
begin
try
bla1;
除了e:Exception do
ShowMessage('bla'+ e.Message);
结束
结束
procedure TForm1.bla1;
begin
try
bla2
除了e:Exception do
ShowMessage('bla1'+ e.Message);
结束
结束
函数TForm1.bla2:boolean;
var ath:TTest;
begin
try
ath:= TTest.Create(true);
InterlockedIncrement(nrthd);
ath.FreeOnTerminate:= True;
ath.aBtn:= Button1;
ath.OnTerminate:= onterm;
运动员
除了e:Exception do
ShowMessage('bla2'+ e.Message);
结束
结束
procedure TForm1.Button1Click(Sender:TObject);
begin
//
try
bla;
而nrthd> 0 do
Application.ProcessMessages;
除了e:Exception do
ShowMessage('Button1Click'+ e.Message);
结束
ShowMessage('done with this');
结束
procedure TForm1.FormCreate(Sender:TObject);
begin
nrthd:= 0;
结束
procedure TForm1.onterm(Sender:TObject);
begin
InterlockedDecrement(nrthd)
end;
结束。
此应用程序的目的只是为了知道访问冲突的捕获位置,以及代码应该如何被写入。
我不明白为什么在行a [2]:='dbwdbkbckbk'; AV不提高
在Delphi 2005中 - 可能大多数其他版本 - 如果异常从执行
方法没有被处理,那么它被调用
Execute
并存储在线程的 FatalException
属性。 (查看 Classes.pas , ThreadProc
。)除非线程被释放,否则没有任何进一步的处理,此时异常也是释放。
因此,您有责任检查该物业并对此进行处理。您可以在线程的 OnTerminate
处理程序中查看它。如果它是非空的,则线程由于未捕获的异常而终止。所以,例如:
procedure TForm1.onterm(Sender:TObject);
var
ex:TObject;
begin
Assert(发件人为TThread);
ex:= TThread(Sender).FatalException;
如果分配(ex)然后开始
//由于异常导致线程终止
如果ex是Exception然后
Application.ShowException(Exception(ex))
else
ShowMessage(ex.ClassName);
end else begin
//线程终止干净
end;
Dec(nrthd);
结束
不需要联锁功能来跟踪线程数。您的线程创建功能和终止处理程序都始终在主线程的上下文中运行。 c> c 和 Dec
已经足够了。
I have a dilemma on how threads work in delphi, and why at a moment when a thread should raise an exception, the exception is not showed. bellow is the code with comments, maybe somebody cand explain to me how that thread, or delphi, is managing access violations
//thread code
unit Unit2;
interface
uses
Classes,
Dialogs,
SysUtils,
StdCtrls;
type
TTest = class(TThread)
private
protected
j: Integer;
procedure Execute; override;
procedure setNr;
public
aBtn: tbutton;
end;
implementation
{ TTest }
procedure TTest.Execute;
var
i : Integer;
a : TStringList;
begin
// make severals operations only for having something to do
j := 0;
for i := 0 to 100000000 do
j := j + 1;
for i := 0 to 100000000 do
j := j + 1;
for i := 0 to 100000000 do
j := j + 1;
for i := 0 to 100000000 do
j := j + 1;
for i := 0 to 100000000 do
j := j + 1;
for i := 0 to 100000000 do
j := j + 1;
for i := 0 to 100000000 do
j := j + 1;
for i := 0 to 100000000 do
j := j + 1;
Synchronize(setnr);
a[2] := 'dbwdbkbckbk'; //this should raise an AV!!!!!!
end;
procedure TTest.setNr;
begin
aBtn.Caption := IntToStr(j)
end;
end.
project's code
unit Unit1;
interface
uses
Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms,
Dialogs,
Unit2, StdCtrls;
type
TForm1 = class(TForm)
Button1: TButton;
procedure Button1Click(Sender: TObject);
procedure FormCreate(Sender: TObject);
private
public
nrthd:Integer;
acrit:TRTLCriticalSection;
procedure bla();
procedure bla1();
function bla2():boolean;
procedure onterm(Sender:TObject);
end;
var
Form1: TForm1;
implementation
{$R *.dfm}
procedure TForm1.bla;
begin
try
bla1;
except on e:Exception do
ShowMessage('bla '+e.Message);
end;
end;
procedure TForm1.bla1;
begin
try
bla2
except on e:Exception do
ShowMessage('bla1 '+e.Message);
end;
end;
function TForm1.bla2: boolean;
var ath:TTest;
begin
try
ath:=TTest.Create(true);
InterlockedIncrement(nrthd);
ath.FreeOnTerminate:=True;
ath.aBtn:=Button1;
ath.OnTerminate:=onterm;
ath.Resume;
except on e:Exception do
ShowMessage('bla2 '+e.Message);
end;
end;
procedure TForm1.Button1Click(Sender: TObject);
begin
//
try
bla;
while nrthd>0 do
Application.ProcessMessages;
except on e:Exception do
ShowMessage('Button1Click '+e.Message);
end;
ShowMessage('done with this');
end;
procedure TForm1.FormCreate(Sender: TObject);
begin
nrthd:=0;
end;
procedure TForm1.onterm(Sender: TObject);
begin
InterlockedDecrement(nrthd)
end;
end.
the purpose of this application is only to know where the access violation is catched, and how the code should be written.
I can not understand why in the line "a[2] := 'dbwdbkbckbk';" the AV is not raised.
In Delphi 2005 — and probably most other versions — if an exception escapes from the Execute
method without being handled, then it is caught by the function that called Execute
and stored in the thread's FatalException
property. (Look in Classes.pas, ThreadProc
.) Nothing further is done with that exception until the thread is freed, at which point the exception is also freed.
It's your responsibility, therefore, to check that property and do something about it. You can check it in the thread's OnTerminate
handler. If it's non-null, then the thread terminated due to an uncaught exception. So, for example:
procedure TForm1.onterm(Sender: TObject);
var
ex: TObject;
begin
Assert(Sender is TThread);
ex := TThread(Sender).FatalException;
if Assigned(ex) then begin
// Thread terminated due to an exception
if ex is Exception then
Application.ShowException(Exception(ex))
else
ShowMessage(ex.ClassName);
end else begin
// Thread terminated cleanly
end;
Dec(nrthd);
end;
There's no need for the interlocked functions for tracking your thread count. Both your thread-creation function and your termination handler always run in the context of the main thread. Plain old Inc
and Dec
are sufficient.
这篇关于Delphi线程异常机制的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!