After battling for half a day with that subtle bug, I am posting the workaround and analysis here, in case other stumble on it.
The issue lies with the TWICImage class, which encapsulates Microsoft Windows Imaging Component, and can be triggered in multi-threaded usage scenarios, particularly in services.
TWICImage interfaces with Microsoft Windows Imaging Component through a IWICImagingFactory interface stored in a class variable, which is initialized in TWICImage constructor, and there are three issues:
- The initialization logic is not protected by a critical section, and is not thread safe.
- TWICImage.Destroy clears that class variable once there are no more references, but that logic is not protected either, and not thread-safe.
- If TWICImage is created from a thread where OLE has not been initialized (with CoInitialize f.i.), the initialization will silently fail, and TWICImage will just bomb with an access violation at a later time.
The workaround for all three issues is rather simple: create a TWICImage in your main program or in the initialization section of a unit, and do not release it for the duration of the application.