Delphi thread exception mechanism
http://www.techques.com/question/1-3627743/Delphi-thread-exception-mechanism
i have a dilema 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 := ;
for i := to do
j := j + ;
for i := to do
j := j + ;
for i := to do
j := j + ;
for i := to do
j := j + ;
for i := to do
j := j + ;
for i := to do
j := j + ;
for i := to do
j := j + ;
for i := to do
j := j + ; 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> 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:=;
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 catch, and how the code should be written.
i can not understand why in the line "a[2] := 'dbwdbkbckbk';" the AV is not raised.
thanks in advance and best regards!
hreading is one place where you should swallow exceptions.
The gist of handling Exceptions in threads is that if you want the exception to be shown to the end user,
you should capture it and pass it on to the main thread where it can safely be shown.
You'll find some examples in this EDN thread How to Handle exceptions in TThread Objects.
procedure TMyThread.DoHandleException;
begin
// Cancel the mouse capture
if GetCapture <> then SendMessage(GetCapture, WM_CANCELMODE, , );
// Now actually show the exception
if FException is Exception then
Application.ShowException(FException)
else
SysUtils.ShowException(FException, nil);
end; procedure TMyThread.Execute;
begin
FException := nil;
try
// raise an Exception
raise Exception.Create('I raised an exception');
except
HandleException;
end;
end; procedure TMyThread.HandleException;
begin
// This function is virtual so you can override it
// and add your own functionality.
FException := Exception(ExceptObject);
try
// Don't show EAbort messages
if not (FException is EAbort) then
Synchronize(DoHandleException);
finally
FException := nil;
end;
end;
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;
We can also reraise FatalException.
Reraising seems not logical but if you have an central exception/error handler in your code and
and if you just want to include thread exceptions into that mechanisim, you can reraise on some rare situation :
procedure TForm1.onterm(Sender: TObject);
var
ex: Exception;
begin
Assert(Sender is TThread);
ex := Exception(TThread(Sender).FatalException);
if Assigned(ex) then
// Thread terminated due to an exception
raise ex;
Dec(nrthd);
end;
How to handle exceptions in TThread objects
By: Corbin Dunn
Abstract: This document describes how to properly handle and show an exception that happens in a thread.
Question:
I have a TThread object which may raise an exception in the Execute procedure.
When an exception is raised, I want to be able to show that exception to the end user.
How do I go about doing this in the most efficient way?
Answer:
With a TThread object, if you don't catch an exception in the Execute procedure of a TThread,
you may get access violations.
The Delphi IDE may break fine on the exception, but often when the application is run outside of the IDE
you get an "Application error has occurred" exception and your application stops running.
If you don't care about showing the end user that an exception occurred,
you can simply wrap your Execute procedure with a try..finally block such as:
procedure TMyThread.Execute;
begin
try
// Do your thread stuff here
except // Eat all exceptions
end;
end;
Quite often, this isn't the best solution and you will want to show the message to the end user,
or allow your application to further process the message.
The easiest way to do this, is to add an Exception object to your TThread class,
and call the appropriate handler based on the type of exception.
Here is an example of how to do this.
The project consists of one form with a Button placed on it:
unit Unit1; interface uses
Windows, Messages, SysUtils, Classes,
Graphics, Controls, Forms, Dialogs, StdCtrls; type
TForm1 = class(TForm)
Button1: TButton;
procedure Button1Click(Sender: TObject);
private
{ Private declarations }
public
{ Public declarations }
end; TMyThread = class(TThread)
private
FException: Exception;
procedure DoHandleException;
protected
procedure Execute; override;
procedure HandleException; virtual;
public
end; var
Form1: TForm1; implementation {$R *.DFM} procedure TMyThread.DoHandleException;
begin
// Cancel the mouse capture
if GetCapture <> then SendMessage(GetCapture, WM_CANCELMODE, , );
// Now actually show the exception
if FException is Exception then
Application.ShowException(FException)
else
SysUtils.ShowException(FException, nil);
end; procedure TMyThread.Execute;
begin
FException := nil;
try
// raise an Exception
raise Exception.Create('I raised an exception');
except
HandleException;
end;
end; procedure TMyThread.HandleException;
begin
// This function is virtual so you can override it
// and add your own functionality.
FException := Exception(ExceptObject);
try
// Don't show EAbort messages
if not (FException is EAbort) then
Synchronize(DoHandleException);
finally
FException := nil;
end;
end; procedure TForm1.Button1Click(Sender: TObject);
begin
// Create an instance of the TMyThread
with TMyThread.Create(True) do
begin
FreeOnTerminate := True;
Resume;
end;
end; end.
vv
Delphi thread exception mechanism的更多相关文章
- Delphi之Exception获得错误信息(简单好理解)
Delphi之Exception获得错误信息 相关资料: http://www.cnblogs.com/hackpig/archive/2010/02/15/1668547.html 实例代码: 1 ...
- Delphi:Exception输出堆栈信息
起源: 用习惯了c#之Exception的StackTrace,在程序出异常crash时候能够以其定位出问题的模块及行号,用回Delphi 2009,发现没有这东西. 显然,在编译环境日新月异的今天, ...
- delphi:Exception EInvalidPointer in module Project1.exe
在用delphi XE5编程时遇到如下问题: Exception EInvalidPointer in module Project1.exe at 00007595. Invalid pointer ...
- Delphi Thread.Queue与Synchronize的区别(差别: Synchronize是阻塞,Queue是非阻塞)
前话: 其实大家要学会看源码, 我接下来要说的这些东东,与其等别人讲,还不如自己搞几个代码试一下,印象还深刻点 TThread.Queue和TThread.Synchronize的区别, 效果上:二 ...
- delphi.thread.同步
注意:此文只是讲线程间的同步,其它同步不涉及. 线程同步是个好话题,因为写线程经常会遇到,所以就写写自己知道的东西. D里面,同步(特指线程同步)从线程的角度来分,有几种情况: 1:主线程与工作线程的 ...
- delphi.thread.线程循环执行体结构
线程话题太大,又都是些坑,不知从哪方面讲起,所以,想一出是一出了. 不管怎样,我们从开始使用D,不管有没有用线程,其实它已经帮我们做了一个最完整的线程执行处理:Application.Run. 这行A ...
- Delphi之Exception获得错误信息
1 unit Unit1; 2 3 interface 4 5 uses 6 Windows, Messages, SysUtils, Variants, Classes, Graphics, Con ...
- Delphi Thread
Thread给几点说明:1.MyThread的实例作为TForm1的成员变量2.不要使用Form1这个全局变量,线程中可要使用它的Handle,你可以在Form中创建MyThread的实例时把Hand ...
- Delphi DLL制作和加载 Static, Dynamic, Delayed 以及 Shared-Memory Manager
一 Dll的制作一般分为以下几步:1 在一个DLL工程里写一个过程或函数2 写一个Exports关键字,在其下写过程的名称.不用写参数和调用后缀.二 参数传递1 参数类型最好与window C++的参 ...
随机推荐
- Datawindow.net+access数据窗口制作方法
1) 数据字典:采用SQLServer桌面程序来创建数据字典.配置正确的pbl文件生成输入列表. 在SQLServers查询器中执行select * from pbcatedt where pbe_n ...
- TextView------文字底部或者中间加横线
promotionLinkText = (TextView) this .findViewById(R.id. text_promotion_link ); 中间加横线 promotionLinkTe ...
- Android开发中这些小技巧
http://blog.csdn.net/guxiao1201/article/details/40655661 http://blog.csdn.net/guxiao1201/article/det ...
- list 容器 排序函数.xml
pre{ line-height:1; color:#f0caa6; background-color:#2d161d; font-size:16px;}.sysFunc{color:#e54ae9; ...
- mybatis系列-14-延迟加载
14.1 什么是延迟加载 resultMap可以实现高级映射(使用association.collection实现一对一及一对多映射),association.collection具备延迟加载 ...
- N皇后问题--回溯法
1.引子 中国有一句古话,叫做“不撞南墙不回头",生动的说明了一个人的固执,有点贬义,但是在软件编程中,这种思路确是一种解决问题最简单的算法,它通过一种类似于蛮干的思路,一步一步地往前走,每 ...
- Linux_系统信息
公司里一些仿真软件得进Linux系统,好奇公司用的什么Linux版本,于是搜罗了几个命令如下: 1 uname - Print system info -a, print all info -s, ...
- java&c# dec 加密,通用
java /** * 解密DES * @param key 密钥,长度必须是8的倍数 * @param data 数据源 * @return 解密内容 */ public final static S ...
- gVIM 简洁配置 in Windows
原文链接:http://www.errdev.com/post/2/ 捣鼓了一段时间的VIM,神器终归是神器,果然编码效率提升了许多,当然还需要很多插件来配合.自己装插件很麻烦,还要有Vundle这个 ...
- SQL Server数学函数
数学函数 1.计算绝对值ABS ABS函数对一个数值表达式结果计算绝对值(bit数据类型除外),返回整数. 语法结构: ABS(数值表达式) 返回值:与数值表达式类型一致的数据 示例: ) --输出 ...