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. android性能小贴士 翻译

    转自http://developer.android.com/training/articles/perf-tips.html 性能小贴士: 这篇文档主要一些微优化可以提升应用程序性能,但是这些改变不 ...

  2. 嵌入式 hi3518平台以太网网络模块设计包括重连机制和网线检测机制

    <span style="font-family:Courier New;"> #include <sys/types.h> #include <st ...

  3. .net中判断距离高考多长时间的js函数

    在JS中判断距离高考(此处举例高考)的时间函数 JS中代码: function djs() { var severtime= new Date(); //获取服务器日期 var year=severt ...

  4. 数往知来 CSS<十二>

    div+css基础 一.外部样式<!--外部样式可以使网页与样式分离,分工处理 1.写网页,主要提供内容,一般都会有固定的结构,具有id等属性的标签包括特定的内容 2.根据结构写样式另存为css ...

  5. javascript常用的小知识

    1. oncontextmenu="window.event.returnvalue=false" 将彻底屏蔽鼠标右键 <table border oncontextmenu ...

  6. 《学习OpenCV》练习题第四章第七题abc

    题外话:一直是打算把这本书的全部课后编程题写完的,中间断了几个月,一直忙于其他事.现在开始补上. 这道题我不清楚我理解的题意是不是正确的,这道题可以练习用OpenCV实现透视变换(可以用于矫正在3维环 ...

  7. ASP.NET MVC - 发布网站

    原文地址:http://www.w3school.com.cn/aspnet/mvc_publish.asp 学习如何在不使用 Visual Web Developer 的情况下发布 MVC 应用程序 ...

  8. cc.RepeatForever和cc.Spawn冲突

    正确 var tmpShip3 = cc.Sprite.createWithSpriteFrameName("w1_1.png"); tmpShip3.setPosition(,) ...

  9. 第三百三十五天 how can I 坚持

    晚上回来看了个奥斯卡影片,<疯狂的麦克斯-狂暴之路>,挺震撼的场面.导演确实挺厉害,不知道是怎么想象出来的. 睡觉,明天继续.

  10. IdTCPServer

    IdTCPServer1 Server本身就支持多线程,一个服务端连接多个客户端. IdTCPServer1.Bindings.Add.IP := '127.0.0.1';IdTCPServer1.B ...