delphi – 在另一个线程中引发异常
如何在Delphi中的另一个线程中引发异常?
我有线程1和线程2,我想在线程1中引发异常并在线程2中捕获它. 编辑 我现在可以看到我最初的解释令人困惑.我想要做的是从线程1初始化线程2中的异常引发.因此引发异常并在线程2中捕获,但此过程由线程1控制. 解决方法
这是一段将异常引发到另一个线程的示例代码.它使用SuspendThread来停止线程,GetThreadContext来读取线程的寄存器,改变EIP(指令指针),使用SetThreadContext然后使用ResumeThread来重启线程.有用!
UKilThread单位 很好地打包用于提供AbortThread()例程的重用单元: unit UKillThread; interface uses Classes,Windows,SysUtils; procedure AbortThread(const Th: TThread); implementation // Exception to be raized on thread abort. type EThreadAbort = class(EAbort); // Procedure to raize the exception. Needs to be a simple,parameterless procedure // to simplify pointing the thread to this routine. procedure RaizeThreadAbort; begin raise EThreadAbort.Create('Thread was aborted using AbortThread()'); end; procedure AbortThread(const Th: TThread); const AlignAt = SizeOf(DWORD); // Undocumented; Apparently the memory used for _CONTEXT needs to be aligned on DWORD boundary var Block:array[0..SizeOf(_CONTEXT)+512] of Byte; // The _CONTEXT structure is probably larger then what Delphi thinks it should be. Unless I provide enough padding space,GetThreadContext fails ThContext: PContext; begin SuspendThread(Th.Handle); ZeroMemory(@Block,SizeOf(Block)); ThContext := PContext(((Integer(@Block) + AlignAt - 1) div AlignAt) * AlignAt); ThContext.ContextFlags := CONTEXT_FULL; if not GetThreadContext(Th.Handle,ThContext^) then RaiseLastOSError; ThContext.Eip := Cardinal(@RaizeThreadAbort); // Change EIP so we can redirect the thread to our error-raizing routine SetThreadContext(Th.Handle,ThContext^); ResumeThread(Th.Handle); end; end. 演示项目 以下是使用AbortThread的方法: program Project23; {$APPTYPE CONSOLE} uses SysUtils,Classes,UKillThread; var Th: TThread; type TTestThread = class(TThread) public procedure Execute;override; end; { TTestTrehad } procedure TTestThread.Execute; var N: Integer; begin try N := 1; while not Terminated do begin WriteLn(N); Inc(N); Sleep(1000); end; except on E:Exception do WriteLn(E.ClassName + ' / ' + E.Message); end; end; begin Th := TTestThread.Create(False); WriteLn('Press ENTER to raize exception in Thread'); ReadLn; AbortThread(Th); WriteLn('Press ENTER to exit'); ReadLn; end. 放弃 在确实使用它之前,请确保您了解此代码的作用.这绝不是正确的Terminate – Terminated逻辑(即协作线程关闭)的替代品,但它是TerminateThread()的更好替代品.这是在.NET Thread.Abort()方法之后建模的.我不知道实际的.NET方法是如何实现的,但是由于使用此代码的潜在问题是相似的,因此: >该方法实际上并不终止该线程,它在线程的上下文中引发了一个EAbort派生的异常.线程的代码可能会捕获异常.这是不太可能的,因为不应该处理EAbort异常. (编辑:李大同) 【声明】本站内容均来自网络,其相关言论仅代表作者个人观点,不代表本站立场。若无意侵犯到您的权利,请及时与联系站长删除相关内容! |