Jump to content
brk303

Waiting for anonymous methods to complete

Recommended Posts

I'm considering the following implementation for handling anonymous methods:


 

TSomeClass = class

    fAnonymousMethods: integer;

    procedure Destroy; override;
procedure TSomeClass .Destroy;
var
  i: integer;
begin
  repeat
    AtomicExchange(i, fAnonymousMethods);
    if i > 0 then
      Sleep(10);
  until i = 0;
  inherited;
end;

 

And, predictably in the anonymous method:


 

    AtomicIncrement(fAnonymousMethods);
    try

   // perform actual task

    finally
      AtomicDecrement(fAnonymousMethods);
    end;

 

In my particular use case, network communication, there may be multiple anonymous threads sending queued up data in the background.

The desired behaviour on shutdown is to complete sending whatever data may be queued up, which realistically takes a fraction of a second.

So, if I use a simple integer counter, as in the code above, and wait a bit, that should solve the problem, right ?

 

I don't see any flaws in this approach, other than it perhaps being a somewhat dirty shortcut, but is that really a problem, what do you guys think ?

 

 

 

Share this post


Link to post
3 hours ago, brk303 said:

So, if I use a simple integer counter, as in the code above, and wait a bit, that should solve the problem, right ?

You have a race condition.  You are incrementing the counter at the point where the work is actually performed, but if the work is merely queued but the work thread hasn't actually started the work yet, then the counter may not have been incremented yet by the time you compare it in your destructor.  You need to increment the counter at the point where the work is being queued, not where it is acted on.

 

You didn't say which platform(s) you are targeting, On Windows for instance, a better strategy would be to put the thread's handles into an array, and then you can use (Msg)WaitForMultipleObjects() to wait for the handles to be signaled when the threads are fully terminated.  However, you mention anonymous threads, so be aware that TThread.CreateAnonymousThread() sets TThread.FreeOnTerminate=true, which doesn't mix well with waiting on thread handles.  So you would have to manually set FreeOnTerminate=false when starting the anonymous threads, and then free the threads yourself when they are finished running.

Share this post


Link to post
Posted (edited)

Another simple option could be creating a System.Threading.ThreadPool, putting tasks in it and just destroying the Threadpool in the destructor of your TSomeClass. The Threadpool destructor will finish all tasks that are queued.

Edited by Der schöne Günther

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

×