Sign in Join

Live chat for Free Pascal, Lazarus, Delphi and every Pascal programmer.

Mailing lists / lazarus / 2011-09

Application.QueueAsyncCall and checking if object still exists

7 messages · 3 people · –

Reply by email Subscribe to this list Your subscription

Read-only archive. Use j and k to move between messages.

Krzysztof

Hi,

I have some object which create and execute thread. This thread do some http requests (synapse) and send progress to the object by Application.QueueAsyncCall(MyObject.MyHandleProc, AProgress), it is designed for multithread - have critical section, so I can call it from thread to main thread. But I have problem which occurs some times. In object destructor I clear async queue by calling Application.RemoveAsyncCalls (which is thread safe too). But if thread waiting in critical section (because main thread block it with RemoveAsyncCalls) then after main thread leave critical section, thread post progress but should not because object is going to destroy. This occurs Access violation in ProcessAsyncCallQueue because method MyObject.MyHandleProc doesn't exists any more, this is only pointer to that method. Can ProcessAsyncCallQueue some how check if target still exists?

Regards
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://lists.lazarus.freepascal.org/pipermail/lazarus/attachments/20110922/ad5103a7/attachment.html>

Reply by email

Flávio Etrusco
to Krzysztof

2011/9/22 Krzysztof :

Show quoted text 18 lines
Hi, I have some object which create and execute thread. This thread do some http requests (synapse) and send progress to the object by Application.QueueAsyncCall(MyObject.MyHandleProc, AProgress), it is designed for multithread - have critical section, so I can call it from thread to main thread. But I have problem which occurs some times. In object destructor I clear async queue by calling Application.RemoveAsyncCalls (which is thread safe too). But if thread waiting in critical section (because main thread block it with RemoveAsyncCalls) then after main thread leave critical section, thread post progress but should not because object is going to destroy. This occurs Access violation in ProcessAsyncCallQueue because method MyObject.MyHandleProc doesn't exists any more, this is only pointer to that method. Can ProcessAsyncCallQueue some how check if target still exists? Regards

Why not destroy it with Queued call too?

-Fl?vio

Reply by email

Michael Schnell
to Michael Schnell
Michael Schnell wrote
IMHO the better way is to check if the object exists in the main thread when called.

Obviously you need to use a procedure of some other object (e.g. the thread itself) and (if necessary) provide the object i9n question (that might be destroyed and NILled) as a parameter.

(BTW if the user programmer does not care for it there is no way to detect if an object is destroyed. It would need to be NILled by same.So a library function can't check this.)

-Michael

Reply by email

Krzysztof
to Michael Schnell

Details. This is only draft:

TMyThread = class(TThread)
protected
  procedure Execute; override;
end;
TMyObject = class
private
  FHttpThread: TMyThread;
  procedure ProgressProc(Data: PtrInt);
end;
TProgressObj = class
  Status: String;
  Id: Integer;
end;
procedure TMyThread.Execute;
var
  i: Integer;
  prg: TProgressObj;
begin
  for i:=1 to 10 do
  begin
    prg := TProgressObj.Create;
    prg.Status := 'Step ' + inttostr(i);
    prg.Id := i;
    Application.QueueAsyncCall(MyObj.ProgressProc, prg);
  end;
end;
procedure TMyObject.ProgressProc(Data: PtrInt);
var
  prg: TProgressObj;
begin
  Memo1.Append(prg.Status);
  prg.Free;
end;

So, when MyObj is destroyed, Queue list have nonexistent pointer to ProgressProc
and I must clear it because I created object and don't want memory leaks. Main problem is: I don't know how to tell thread (which is locked in QueueAsyncCall critical section), that method pointer which he trying to post, doesn't exists anymore.

2011/9/22 Michael Schnell

Show quoted text 25 lines
On 09/22/2011 02:56 PM, Michael Schnell wrote: > > > IMHO the better way is to check if the object exists in the main thread > when called. > Obviously you need to use a procedure of some other object (e.g. the thread itself) and (if necessary) provide the object i9n question (that might be destroyed and NILled) as a parameter. (BTW if the user programmer does not care for it there is no way to detect if an object is destroyed. It would need to be NILled by same.So a library function can't check this.) -Michael -- ______________________________**_________________ Lazarus mailing list .**freepascal.org http://lists.lazarus.**freepascal.org/mailman/**listinfo/lazarus<http://lists.lazarus.freepascal.org/mailman/listinfo/lazarus>

-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://lists.lazarus.freepascal.org/pipermail/lazarus/attachments/20110922/1e945f19/attachment.html>

Reply by email

Michael Schnell
to Krzysztof
Krzysztof wrote 5 lines
Main problem is: I don't know how to tell thread (which is locked in QueueAsyncCall critical section), that method pointer which he trying to post, doesn't exists anymore.

Seemingly you want to create a queue of objects and/or strings that are sent from the Thread to the Main thread, and want to be sure that the main thread in fact handles all of them.

If just doing a progress indicator, it would not harm if some events in the main thread would be dropped, so IMHO it would be a better way to use a global integer variable that is written by the thread and read by the main thread. So no object or string creation is necessary.

If you really need to dedicatedly handle all events I;HO a good way is to use a TThreadList with "add" in the thread.

Another thing to watch is how the reference counting strings are handled. Are they correctly kept life when the function that moves them into the object is left ? Are they correctly freed when the object is freed ?

I usually try to avoid handling strings in such a creative way.

-Michael

Reply by email

Krzysztof
to Michael Schnell

Hm, TThreadList is good idea. I could try create global ThreadList and add http responses from thread into that list, then only post some notify message to main thread which would mean that main thread should peek and parse objects from ThreadList. I try with that. Thanks

2011/9/23 Michael Schnell

Show quoted text 35 lines
On 09/22/2011 05:28 PM, Krzysztof wrote: > > Main problem is: I don't know how to tell thread (which is locked in > QueueAsyncCall critical section), that method pointer which he trying to > post, doesn't exists anymore. > > Seemingly you want to create a queue of objects and/or strings that are sent from the Thread to the Main thread, and want to be sure that the main thread in fact handles all of them. If just doing a progress indicator, it would not harm if some events in the main thread would be dropped, so IMHO it would be a better way to use a global integer variable that is written by the thread and read by the main thread. So no object or string creation is necessary. If you really need to dedicatedly handle all events I;HO a good way is to use a TThreadList with "add" in the thread. Another thing to watch is how the reference counting strings are handled. Are they correctly kept life when the function that moves them into the object is left ? Are they correctly freed when the object is freed ? I usually try to avoid handling strings in such a creative way. -Michael -- ______________________________**_________________ Lazarus mailing list .**freepascal.org http://lists.lazarus.**freepascal.org/mailman/**listinfo/lazarus<http://lists.lazarus.freepascal.org/mailman/listinfo/lazarus>

-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://lists.lazarus.freepascal.org/pipermail/lazarus/attachments/20110923/e8b44a72/attachment-0001.html>

Reply by email