Jump to content
chkaufmann

How to avoid calls to invalid events?

Recommended Posts

I have a controller for "remote files". If the file is not yet on the local disk, I download it in the background (using a IOmniBackgroundWorker) and then call an event when the file is available. 

procedure TMyController.GetFile(const AFilename: String; AOnFileAvailable: TNotifyEvent);
begin
  ...
end;

AOnFileAvailable is a method of a form which loads the file to display it. Now it may happen that the form will be closed before the download is finished and in this case a call to AOnFileAvailable will cause an access violation.

 

My question: What is the common pattern to solve this issue? I was thinking about passing an object/interface instead of the event so the form can set it to invalid before it's destroyed. But maybe this is solved using existing code from the OmniThread Library?

 

Christian

Share this post


Link to post

Do you actually need the form in the event handler? If not, you could pass a plain procedure pointer instead.

Share this post


Link to post

Yes, but the procedure will access for example a TOleContainer to display Word and Excel files. And once the form is gone, the Container is gone as well.

Share this post


Link to post

Your idea with reference counted object (you have to pass it as interface and not as const to increase its reference count) and invalidating a flag will serve the purpose.

 

I don't use OmniThread library, so I don't know if there are some built in mechanisms to take care of such cases.

 

 

Share this post


Link to post
1 hour ago, Dalija Prasnikar said:

Your idea with reference counted object (you have to pass it as interface and not as const to increase its reference count) and invalidating a flag will serve the purpose.

But would that not simply delay the problem? Since he said that the code must access the form, the callback method must still check whether the form still exists when it wants to write to the OLE container on the form.

Share this post


Link to post
7 minutes ago, dummzeuch said:

But would that not simply delay the problem? Since he said that the code must access the form, the callback method must still check whether the form still exists when it wants to write to the OLE container on the form.

If you invalidate flag sitting inside interface when form is going to be destroyed, then you know form is no longer valid and you can skip calling methods on invalid reference.

Share this post


Link to post

That was my idea as well. I did some more research in the internet and Maybe I will use an IOmniFuture<T>. But I have to test this first. Not sure if the OnTerminated event is called everytime and if the CancellationToken is already signaled if all references to it are released. Otherwise it will be easier to create my own call back object/interface.

Share this post


Link to post

Create an account or sign in to comment

You need to be a member in order to leave a comment

Create an account

Sign up for a new account in our community. It's easy!

Register a new account

Sign in

Already have an account? Sign in here.

Sign In Now
×