问题描述
我在delphi中有一个线程工作的困境,为什么在一个线程应该引发异常的时候,这个异常没有显示出来。 bellow是带有评论的代码,也许有人可以向我解释这个线程或者delphi是如何管理访问冲突的。//线程代码
$ b $单位Unit2; bc> 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线程异常机制的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持!