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++的参 ...
随机推荐
- zabbix (2.0.6) 历史记录处乱码
1.首先备份数据库 mysqldump -uroot -p123456 zabbix > zabbix.sql 2.设置字符 sed -i 's/latin1/utf8/g' zabbix.sq ...
- pcap文件的文件头的link type
http://www.tcpdump.org/linktypes.html Link-layer header type values LINKTYPE_ name LINKTYPE_ value C ...
- CSS使jsp图片旋转90度
<style > img{ margin:100px auto 0; -moz-transform:rotate(-90deg); -webkit-transform:rotate(-90 ...
- web-ylbtech-数据库备份-数据库设计
ylbtech-DatabaseDesgin:web-ylbtech-数据库备份-数据库设计 DatabaseName:ylbtech Model:备份 Type:数据库备份设计 Url: 1.A,数 ...
- -Xbootclasspath参数、java -jar参数运行应用时classpath的设置方法
当用java -jar yourJarExe.jar来运行一个经过打包的应用程序的时候,你会发现如何设置-classpath参数应用程序都找不到相应的第三方类,报ClassNotFound错误.实际上 ...
- free-jqGrid
PM> Install-Package free-jqGrid jqGrid 是一个用来显示网格数据的jQuery插件,通过使用jqGrid可以轻松实现前端页面与后台数据的ajax异步通信.文档 ...
- STL六大组件之——算法小小小小的解析
参考自侯捷的<stl源码剖析> stl算法主要分为非可变序列算法(指不直接修改其所操作的容器内容的算法),可变序列算法(指可以修改它们所操作的容器内容的算法),排序算法(包括对序列进行排序 ...
- Java多线程学习总结--线程同步(2)
线程同步是为了让多个线程在共享数据时,保持数据的一致性.举个例子,有两个人同时取钱,假设用户账户余额是1000,第一个用户取钱800,在第一个用户取钱的同时,第二个用户取钱600.银行规定,用户不允许 ...
- Hadoop概述
本章内容 什么是Hadoop Hadoop项目及其结构 Hadoop的体系结构 Hadoop与分布式开发 Hadoop计算模型—MapReduce Hadoop的数据管理 小结 1.1 什么是Hado ...
- HDU1227:Fast Food
题目链接:Fast Food 题意:一条直线上有n个饭店,问建造k个原料厂(仍旧在商店位置)得到的最小距离 分析:见代码 //一条直线上有n个饭店,问建造k个原料厂(仍旧在商店位置)得到的最小距离 / ...