In this video, I demonstrate a technique for communicating between threads in a Delphi application, without using typical locking mechanisms such as critical sections. Best Viewed in Full Screen (Recorded 1080p).

Download the source

Reduce development time and get to market faster with RAD Studio, Delphi, or C++Builder. Design. Code. Compile. Deploy.

Start Free Trial   Free Delphi Community Edition   Free C++Builder Community Edition   Upgrade Today  

  • FYI: If you re-watch the last 30 seconds, from time index 35:20, I explain what I just posted in my last comment. Note that the 'test thread' is a class derived from TThread - and note the difference between the 'InPipe' and 'OutPipe' properties. Messages go into the InThread and come out of the OutThread, they are copied from one to the other by the test thread execute method (so inside a second thread).
  • I think you're missing the second thread in the application. The GUI thread pushes a message into a ring buffer, where an aux thread pulls it, the aux thread then pushes that message into a second ring buffer, where the GUI thread pulls it off. There are two threads communicating with each other via ring buffers.
  • Hi, The problem is that its still not threadsafe. If one thread is pushing while the other is pulling then there is a race condition between updating and comparing the index counters. At least you should use InterlockedIncrement and when you reach a border and need to reset the index, you would need to use a waitloop and InterlockedCompareAndExchange which in itself introduce a finegrained lock. best regards Kim/C4D
  • Cool! Thanks for clearing that up. I will definitely be using DisposeOf then :) /Morten
  • In modern versions of Delphi, you should switch to DisposeOf() always. DisposeOf exists to handle differences between the desktop compilers (without ARC memory management) and the mobile compilers (with ARC). Technically if your code will never be used on a mobile target, you don't need DisposeOf, but you never know when you might decide to Port to mobile.
  • Thanks for this sample, Craig. It inspired me to implement something along those lines in one of my applications. I was wondering if you could clarify one thing for me: When do I use DisposeOf rather than FreeAndNil? Keep up the good work :)
  • It's true that the UI thread does both a push and a pull, but those operations are on two different arrays. The second thread is simply copying messages from the first array to the second. While I agree this is a very simple example, it demonstrates a two way communication between the UI thread and the other thread (consider it an echo thread). Perhaps this is the cause of confusion. The second thread need not simply echo the messages from one array to another, but instead could act on messages to do something useful. Echo was just the simplest example I could use.
  • I should rephrase it... one event run under the GUI thread entering the message and another event run under the GUI thread pulling the message.
  • Hi, I maybe missing something... but the source showed one GUI thread entering the message, and another GUI thread (by the OnIdle event) pulling the message. The array is correctly owned by a 2nd thread, but that thread do not interact with the data at all as far as I could tell by glancing over the code :)
  • Two independent threads put messages into, and remove messages from a dynamic array, allowing communication between those threads. This happens without using locking mechanisms such as TCriticalSection. There is literally a descendant of TThread in the source. I feel this post precisely matches his headline.
  • Hi. It seems to me that this article doesnt match its headline very well... In fact there is nothing multithreaded in it. You could just as well have created a TObject holding the dynamic array. Is something missing from the code sample?