There is an unsaved comment in progress. You will lose your changes if you continue. Are you sure you want to reopen the work item?

3

Closed

Multithreading- AdjustToContents not threadsafe

description

Hi,

I have recently upgraded from 0.65 to 0.73 and while I have seen some performance improvements, several reports that run in parallel threads crashed in my UAT environment. It seems the problem is in the AdjustToContents() method.

The error is simple:
In at ClosedXML.Excel.FontBaseExtensions.GetWidth(IXLFontBase fontBase, String text, Dictionary`2 fontCache)
the library is using a static graphics object. Graphics objects are not threadsafe.
You need to create a new one each time you use it or lock it appropriately.

The workaround for this problem is locking the Code which calls AdjustToContents.

Not sure if locking is the right way here, the methods GetWidth and GetHeight are called many times throughout the AdjustToContents function. Locking is not a fast process.
I would recommend passing a graphics object down from the AdjustToContents method to GetWidth and GetHeight and get rid of the static object. This will be thread-safe and get rid of the locking.

While you are at it, two further thread-safety issues in the Extensions class.

1.IntegerExtensions.ToStringLookup:

A normal Dictionary is not threadsafe, especially not writing to it, either lock it or use ConcurrentDictionary. I'm not sure about the dictionary there at all, it might get really huge very fast, considering that you try to cache each and every integer
you pass into it. I'm not sure about the performance gain by this lookup. If it is really that much faster, cache the lookup locally in the method you need it in.

StringExtensions.FixNewLines

Regex object is not threadsafe, simply use the static Regex.Replace/Match etc. methods and .NET will automatically cache the Regex objects for it and make sure it's thread-safe. In that case you should not use the RegexOptions.Compiled option.