一个多月来,加班似乎成了家常便饭,紧追慢赶手头几乎不可能实现的项目,也很少有机会写点什么了。
最近在实现Delphi Server控件组操作Word编辑文档的时候,遇到了3年前就曾遇到的问题,以为这次能够圆满解决,但最后发现还是沿用的老方法--看来对于实现层,我还是个新手啊…好了废话不说,来说说我发明的这个笨法。
问题的由来:
当前项目中有个实现为,用Delphi的Server控件启动一个Word实例,对文档进行操作,并在Word保存退出时读取该文件,并存入数据库。,我将保存文件到数据库的操作作为一个反转回调注册到WordApplication和WordDocument控件中,用于在WordDocument产生OnDocumentClose事件时调用该回调函数,而问题就出现在这里,当WordDocument产生OnDocumentClose事件时,并没有被Free掉,所关联的文件也是被独占了,所以读取文件的操作会执行失败。
3年前写FlaFly播放器时,也遇到了类似问题。Flash控件会响应一个Close的Command,之后会释放整个Flash控件,而这个响应是在Flash控件的OnCommand事件中,所以在一个对象的事件中无法实现自释放。
解决方法:
无奈中,我在每个对象的管理类中增加了一个TTimer作为Server,来监视对象的事件变化,当对象需要自释放时,在响应事件中启动这个Server(一般都要在对象的释放通知事件中来启动这个Server),Server启动后会检测并执行预先设置好的操作,之后停止自己。
不足之处:
该方法只适合解决对象释放通知事件的自释放问题,因为,只有在这个时候,我们才认为Server被通知后,对象立即被释放掉了,而Server的触发间隔基本可以应付一般情况。
当然,如果你的对象需要进行的清理操作时间较长,那么就在Server中定义一个标志符,来对失败的操作(比如读取文件失败)进行重试,直到操作成功执行(即等待对象完全释放)。
后记:
对于该类问题,也许是由于水平有限造成的设计问题,因此,除非一些极端情况,我们应该寻找更加有效的设计方案来解决此类问题。但对于单线程设计中,此方法可以解决某些调用交叉问题。