3
votes

If many asynchronous threads draw in a global TBitmap, it will rise me an error? Should I create my code using a critical section? (From my surf on the internet I found that the TBitmap.Draw is not thread safe)

Another question: If many synchronous threads draw in a global TBitmap and a VCL Timer read asynchronously the content from the TBitmap will this rise me an error?

Thanks!

4
Do you really need a global TBitmap? I'm guessing a bit, now, but I think you need more than one TBitmap instance. The instance being rendered by the TTimer should not be the one currently being written by the other threads.Martin James
The trick is, with video rendering, to keep a queue of ready-prepared TBitmaps so that the TTimer can always dequeue one and render it without any syncho. with the other threads that are busy preparing other bitmaps to be queued up. Synchonization with mutexes, critical sections etc. on one bitmap instance will be messy and perform very poorly, even if you can get it to work correctly. Multithreaded performance is safer and quicker if you can avoid as much locking/synchro as possible - thave threads work on a different bitmap than the one being rendered.Martin James
@Martin You can't really do video rendering on a TTimer. You need something more precise than that.David Heffernan
@DavidHeffernan - you can! Problems only arise if the GUI thread, (and so the TTimer), cannot get enough CPU to keep up with the frame rate. If that is the case, it doesn't really matter what kind of VCL/multimedia timer you use and it's time to move to DirectX etc.Martin James
@Martin Hmm, I'm not convinced. I think you need a real timer.David Heffernan

4 Answers

5
votes

Yes, you do need to protect the TBitmap from concurrent access across multiple threads. A critical section is fine for serializing your drawing code, HOWEVER that is not enough by itself! The main thread caches GDI resources and performs cleanup on them periodically, which will affect your TBitmap. As such, you will ALSO need to Lock/Unlock() the TBitmap.Canvas whenever drawing/rendering to ensure the VCL does not rip out its resources behind your back.

4
votes

Since your threads are all modifying the same bitmap, you need to serialize all access to that bitmap. That means reading its contents as well as writing to it.

Of course, this assumes that multiple threads drawing to a shared bitmap is the right solution to your problem. Without knowing what your actual problem is, I could not comment on that.

UPDATE

You must also use Lock/Unlock when drawing to the bitmap because of the issue described in Remy's answer. Which should be the accepted answer to this question.

1
votes

Use monitors or semaphores to control your threads when they do changes in your TBitmap Pixels !

0
votes

Can you use the TThread.Synchronize method instead?

http://docs.embarcadero.com/products/rad_studio/delphiAndcpp2009/HelpUpdate2/EN/html/delphivclwin32/Classes_TThread_Synchronize@[email protected]

According to the doco for TThread class

Following are issues and recommendations to be aware of when using threads:

Keeping track of too many threads consumes CPU time; the recommended limit is 16 active threads per process on single processor systems.

When multiple threads update the same resources, they must be synchronized to avoid conflicts.

Most methods that access an object and update a form must only be called from within the main thread or use a synchronization object such as TMultiReadExclusiveWriteSynchronizer.