程序退出时的异常(100分)

  • 主题发起人 主题发起人 waterflow
  • 开始时间 开始时间
W

waterflow

Unregistered / Unconfirmed
GUEST, unregistred user!
程序运行的时候产生几个线程,每个线程有自己的ADOConnection和adoquery用于数据处理【从一个数据源获取数据 插入到另外一个数据源】。
每个线程如果成功生成 则指定他的onterminate事件【调用线程本声的一个函数,用于将query的active设置为false和将connection的connected设置为false】
程序退出的时候 判断各个线程是否结束,没有结束则terminte 当所有的线程全部结束的时候 applicateion.terminate。
实际的情况是:
在线程进行数据处理的时候,程序的退出一般会出现异常,有时候程序不能退出,需要强制终止。
有时候可以正常退出。
退出异常的时候会出现两个错误提示框:
应用程序发生未知软件异常ox0eedfade,位置为0x77e7e8bb

Exception EOLEException in module exe文件名 at 00087BE0 在异步运行时,操作不能被执行。
我在使者解决这一问题的过程中 不管是否使用try都没有用,而且通过消息框定位异常消息出现在执行 application.terminate语句时。
谁知道这么解决这一问题。
3x
 
如果线程在进行数据库操作时你执行关闭线程的操作语句应该不能马上关闭线程吧,applicateion.terminate退出程序时线程没有被关闭,所以会出现错误。建议在线程中进行数据库操作时尽可能的缩短每次执行的时间。
 
对数据库的操作用事务来控制。
 
对数据库的操作用事务来控制。 和程序退出异常没有什么联系吧
次时代:
我那程序主要是数据采集 由于各种原因不能缩短每次执行的时间
 
我一直有这样的问题:
在线程中进行数据库操作,正常关闭还好。如果操作没有完成,这是要关闭程序。
一般都会抱错的。最后没办法。判断操作没有完成时,若要关闭程序用TerminateProcess()这个方法。这样不抱错,但总感觉不好。
 
fu_qi_ming办法是可行 好像也没有内存泄漏。【用工具检查过】 谢谢!
今天试了一天,总想正常的使用terminate来关闭程序。经过实践发现如果线程的execute中检测到terminated则线程真的结束。 而且等到此时再调用application的terminate,程序退出不报错。
本来做了一个线程A来等待其他数据处理线程的结束 waitfor 但是发现程序等很长时间线程A也不结束【比可以安全关闭程序的时间还长】 为何。
大概的逻辑如下:
关闭程序过程:
如果有线程不是terminated则terminate 该线程
如果有线程不是terminated则 线程A resume
如果线程A terminated则程序退出
【线程A 的execute中只有几个 waitfor语句 后来加terminate也没有用】
这样的逻辑的结果是线程A从来没有terminated过。
谁有较好的办法真正解决这一问题?
 
一般退出异常产生,会有这么几种可能(供参考):
对象已经释放了,但由于设置了宿主,所以宿主释放时将通知对象进行释放,所以产生了地址错误。
对象正在使用,或者对象没有指定宿主,退出是对象还是没有释放或者正在使用。
 
我在窗口关闭时,调用下面这个过程,就不会出错
procedure win_api;
//win32错误 87 参数不正确
var st:TStartUpInfo;pp:TProcessInformation;ppp:Thandle;tt:Cardinal;
begin
try
FillChar(st,sizeof(st),#0);
with stdo
begin
cb:=sizeof(st);
dwFlags:=StartF_UsesTDHandles or STARTF_USESHOWWINDOW;
lptitle:=nil;
wShowWindow:=SW_HIDE;
end;
CreateProcess('',nil,nil,nil,true,DETACHED_PROCESS,nil,nil,st,pp);
ppp:=OpenProcess(PROCESS_ALL_ACCESS, FALSE,pp.dwProcessId );
GetExitCodeProcess(ppp,tt);
Exitprocess(tt);
except
end;
end;
 
dana 你的方法和 fu_qi_migng的类似。
我希望做到程序最好正常退出,也就是程序推出前检查是否有线程还没有完全关闭,有提示不退出程序,否则退出【application.terminate】
 
我想是这样的,数据库操作没有完成时,那个线程的执行路径是结束不了的.
程序退出后,执行路径还在,当继续执行时抱错.
所以我想重点是怎样把那个线程完全结束掉.
你要立即结束一个正在执行的线程.
用TThread.Terminate和ExitThread()肯定是不行的.
所以还是TerminateThread();但是我用了这个函数结束线程,好像还是会抱错,
不知何故?搂住试试.
我想问题时怎样结束那个线程,正常的结束好像是不能做到的.
 
fu_qi_ming说的应该是正确的,你可以在程序中加入一个退出变量,当要退出程序时置一下这个变量,所有的线程在每次数据采集过程中都要检查一下这个变量,置了就不要再作操作而直接退出本线程。这样的话主线程中只要置了变量后就等待所有线程退出后再关闭程序。可能退出会慢点,可不会出什么错误了。
 
现在的问题是:
假如在这个线程中已经有一个数据库查询很耗时(十几分钟),我现在要退出程序
怎办了?
(我们要在这个前提下讨论,我想是没有办法正常退出的.)
 
大家看看还有什么办法,
 
fu_qi_ming 我试过 一样
我的程序中所有线程在execute中主要的语句是while 1=1的循环,在循环开始处判断线程是否terminated,如果是,则发送相应的消息。主程序处理消息,显示信息。
通过实际实践发现:
由于有些数据库访问时间太长,在进行程序关闭时【不一定会立即关闭程序】很久后在主程序的界面上可以看到线程结束的信息,通过各种检测手段感觉数据库访问此时确实结束。但是如果在看到线程结束消息之前【中间时间长的可能有1分钟以上】,访问线程是否terminated【我自己编写的函数 访问terminated属性】,此时会返回terminated。 为何会出现这种结果?? delphi中线程的terminated属性是什么时候修改的?
如果数据库访问时间短,程序很快就会看到相应线程结束的消息【3妙以内】
本来想通过线程结束消息来处理程序关闭情况,但是在实际中有时候会出现等了很长时间一些线程结束消息收不到【或根本没有发送】,而且这样的线程还是没有加入数据库处理函数,吓的我不敢以这种逻辑进行处理,只能用强制关闭的办法。【个人感觉这个方法可行,但实际中碰到的问题又不好理解 准备等手头的活干完后再仔细研究,这段时间没有时间】
至于如果数据库处理时间很长几分钟以上,此时想立即关闭程序,我觉得除了使用强制关闭外可能没有什么好的办法了。【除非自己编写底层访问数据库的相关库】
如果没有好的办法 我就结贴 发分。
再明确一下:
我希望的程序关闭逻辑是:
如果所有线程结束【内部的数据库处理操作全部结束】 则 application.terminated
如果有线程没有结束 显示相应的提示信息 强行关闭或过一会重试
关键是如何稳定、准确、及时的的判断线程是否结束
再次谢谢各位的高见
 
由于有些数据库访问时间太长,在进行程序关闭时【不一定会立即关闭程序】很久后在主程序的界面上可以看到线程结束的信息,通过各种检测手段感觉数据库访问此时确实结束。但是如果在看到线程结束消息之前【中间时间长的可能有1分钟以上】,访问线程是否terminated【我自己编写的函数 访问terminated属性】,此时会返回terminated。 为何会出现这种结果?? delphi中线程的terminated属性是什么时候修改的?
如果数据库访问时间短,程序很快就会看到相应线程结束的消息【3妙以内】
对于上面的疑惑是这样的:
线程结束,是要把它的执行路径走完的。
delphi中线程的terminated属性是什么时候修改的?(是在TThread.Terminate时候改的)代码如下:(此时线程并不结束,只是一个标志为,要你在执行路径中判断这个标志位,进行退出。)
procedure TThread.Terminate;
begin
FTerminated := True;
end;
(其实TThread.Terminate是在主线程中执行的)。
所以线程的关闭与否不能通过访问Terminated来判断。
我建议最好是在执行路径的结尾,发消息给主线程,由主线程,根据消息来判断。
其实用TerminateThread先结束线程,然后结束进程。
进程都结束,肯定所有的资源都释放了,也算安全的关闭了吧。
 
我建议最好是在执行路径的结尾,发消息给主线程,由主线程,根据消息来判断。
我最初的时候就是使用这种逻辑,但是有时候发现有些线程的结束消息接收不到。【这两天倒是正常】。所以没敢用这种逻辑来进行。

反正这种情况较少,中途退出程序的概率很小,先不想再管这一块。主要是手头的事情时间较紧。
谢谢
 
其实用TerminateThread先结束线程,然后结束进程。
进程都结束,肯定所有的资源都释放了,也算安全的关闭了吧。
TerminateThread is used to cause a thread to exit. When this occurs, the target thread has no chance to execute any user-mode code and its initial stack is not deallocated. DLLs attached to the thread are not notified that the thread is terminating.
这种方法也不安全啊!
考虑起来太烦了
我目前用 关闭程序的时候,提示用户看主界面,看到相应的消息就可以再次进行退出操作,否则长时间后选中强制退出选项,强制退出。
再次谢谢fu_qi_ming
过几天我结贴发分。
 
多人接受答案了。
 
后退
顶部