線程中異常處理問題

来源:互联网 发布:in软件下载ipad 编辑:程序博客网 时间:2024/05/16 19:21

    昨天有看到一個帖子,說在線程的execute拋出異常,卻不會提示的問題。經查http://edn.embarcadero.com/article/10452 有對此問題的說明,如下:

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;interfaceuses  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 <> 0 then SendMessage(GetCapture, WM_CANCELMODE, 0, 0);  // 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.
原创粉丝点击