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.pasThreadProc.)

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的更多相关文章

  1. Delphi之Exception获得错误信息(简单好理解)

    Delphi之Exception获得错误信息 相关资料: http://www.cnblogs.com/hackpig/archive/2010/02/15/1668547.html 实例代码: 1 ...

  2. Delphi:Exception输出堆栈信息

    起源: 用习惯了c#之Exception的StackTrace,在程序出异常crash时候能够以其定位出问题的模块及行号,用回Delphi 2009,发现没有这东西. 显然,在编译环境日新月异的今天, ...

  3. delphi:Exception EInvalidPointer in module Project1.exe

    在用delphi XE5编程时遇到如下问题: Exception EInvalidPointer in module Project1.exe at 00007595. Invalid pointer ...

  4. Delphi Thread.Queue与Synchronize的区别(差别: Synchronize是阻塞,Queue是非阻塞)

    前话:  其实大家要学会看源码, 我接下来要说的这些东东,与其等别人讲,还不如自己搞几个代码试一下,印象还深刻点 TThread.Queue和TThread.Synchronize的区别, 效果上:二 ...

  5. delphi.thread.同步

    注意:此文只是讲线程间的同步,其它同步不涉及. 线程同步是个好话题,因为写线程经常会遇到,所以就写写自己知道的东西. D里面,同步(特指线程同步)从线程的角度来分,有几种情况: 1:主线程与工作线程的 ...

  6. delphi.thread.线程循环执行体结构

    线程话题太大,又都是些坑,不知从哪方面讲起,所以,想一出是一出了. 不管怎样,我们从开始使用D,不管有没有用线程,其实它已经帮我们做了一个最完整的线程执行处理:Application.Run. 这行A ...

  7. Delphi之Exception获得错误信息

    1 unit Unit1; 2 3 interface 4 5 uses 6 Windows, Messages, SysUtils, Variants, Classes, Graphics, Con ...

  8. Delphi Thread

    Thread给几点说明:1.MyThread的实例作为TForm1的成员变量2.不要使用Form1这个全局变量,线程中可要使用它的Handle,你可以在Form中创建MyThread的实例时把Hand ...

  9. Delphi DLL制作和加载 Static, Dynamic, Delayed 以及 Shared-Memory Manager

    一 Dll的制作一般分为以下几步:1 在一个DLL工程里写一个过程或函数2 写一个Exports关键字,在其下写过程的名称.不用写参数和调用后缀.二 参数传递1 参数类型最好与window C++的参 ...

随机推荐

  1. Shell教程5-Shell运算符

    Bash 支持很多运算符,包括算数运算符.关系运算符.布尔运算符.字符串运算符和文件测试运算符. 原生bash不支持简单的数学运算,但是可以通过其他命令来实现,例如 awk 和 expr,expr 最 ...

  2. OpenLayers调用arcgis server发布的地图服务

    有两种方式可以调用arcgis server发布的地图服务,一种是rest,一种是wms.  地图的投影为900913,arcgis server为10.0版本,地图服务的空间参考为3857.   与 ...

  3. php curl简单使用

    使用PHP的cURL库可以简单和有效地去抓网页,您只需要运行一个脚本,然后分析一下您所抓取的网页,然后就可以以程序的方式得到您想要的数据了.无论是您想从一个链接上取部分数据,或是取一个XML文件并把其 ...

  4. mysql 1130 ERROR 1130: Host xxx.xxx.xxx.xxx is not allowed to connect to this MySQL server

    mysql -u root -p  mysql;use mysql;  mysql;select 'host' from user where user='root';  mysql;update u ...

  5. 堪称最好的A*算法

    原文地址:http://theory.stanford.edu/~amitp/GameProgramming/ 相关链接:http://www-cs-students.stanford.edu/%7E ...

  6. openGl从零开始之添加颜色

    OpenGL 支持两种颜色模式:一种是 RGBA模式,一种是 颜色索引模式.无论哪种颜色模式,计算机都必须为每一个像素保存一些数据,即通过每一个像素的颜色,来改变整体图形的颜色.不同的是, RGBA ...

  7. Fisher information matrix笔记

    在看FK论文时,fisher information matrix是必须理解的. 从维基百科查阅到,Fisher information matrix是用利用最大似然函数估计来计算方差矩阵. 来源于: ...

  8. 【Unity入门】碰撞检测与触发检测

    版权声明:本文为博主原创文章,转载请注明出处. 在Unity里面,游戏物体的碰撞我们可以通过刚体组件(Rigidbody)和碰撞器组件(Collider)来进行检测.首先在场景里面添加一个Plane面 ...

  9. C#判断程序是由Windows服务启动还是用户启动

    在Windows系统做网络开发,很多时候都是使用Windows服务的模式,但在调度阶段,我们更多的是使用控制台的模式.在开发程序的时候,我们在Program的Main入口进行判断.最初开始使用Envi ...

  10. 2014搜狗前端面经【B事业部】

    本来就投了一份简历,后来又收到了个B事业部的面试电话,今天刚面完一面,总体感觉还是很基础的,其中一名面试官帅到不行啊!另一个也不差,真是幸胡...(sorry,跑题了...) 上来先做了份笔试题,超级 ...