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 [1] 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.