brk303 0 Posted April 29 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
Remy Lebeau 1393 Posted April 29 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
Der schöne Günther 316 Posted April 29 (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 April 29 by Der schöne Günther Share this post Link to post