I get a `System.InvalidOperationException: collection has been modified; enumeration operation cannot be performed`, inexplicably

I get a System.InvalidOperationException: Collection was modified; enumeration operation may not execute System.InvalidOperationException: Collection was modified; enumeration operation may not execute :

 ExceptionLoggingLibrary.LoggingException: Exception of type 'ExceptionLoggingLibrary.LoggingException' was thrown. ---> System.InvalidOperationException: Collection was modified; enumeration operation may not execute. at System.Collections.Generic.List`1.Enumerator.MoveNextRare() at iTextSharp.text.FontFactoryImp.GetFont(String fontname, String encoding, Boolean embedded, Single size, Int32 style, BaseColor color, Boolean cached) [...] 

From what I understand, this exception occurs when an IEnumerable object changes during its enumeration.

Here is the iTextSharp.text.FontFactoryImp.GetFont method:

  public virtual Font GetFont(string fontname, string encoding, bool embedded, float size, int style, BaseColor color, bool cached) { if (fontname == null) return new Font(Font.FontFamily.UNDEFINED, size, style, color); string lowercasefontname = fontname.ToLower(CultureInfo.InvariantCulture); List<string> tmp; fontFamilies.TryGetValue(lowercasefontname, out tmp); if (tmp != null) { // some bugs were fixed here by Daniel Marczisovszky int fs = Font.NORMAL; bool found = false; int s = style == Font.UNDEFINED ? Font.NORMAL : style; foreach (string f in tmp) { string lcf = f.ToLower(CultureInfo.InvariantCulture); fs = Font.NORMAL; if (lcf.ToLower(CultureInfo.InvariantCulture).IndexOf("bold") != -1) fs |= Font.BOLD; if (lcf.ToLower(CultureInfo.InvariantCulture).IndexOf("italic") != -1 || lcf.ToLower(CultureInfo.InvariantCulture).IndexOf("oblique") != -1) fs |= Font.ITALIC; if ((s & Font.BOLDITALIC) == fs) { fontname = f; found = true; break; } } if (style != Font.UNDEFINED && found) { style &= ~fs; } } BaseFont basefont = null; try { try { // the font is a type 1 font or CJK font basefont = BaseFont.CreateFont(fontname, encoding, embedded, cached, null, null, true); } catch (DocumentException) { } if (basefont == null) { // the font is a true type font or an unknown font trueTypeFonts.TryGetValue(fontname.ToLower(CultureInfo.InvariantCulture), out fontname); // the font is not registered as truetype font if (fontname == null) return new Font(Font.FontFamily.UNDEFINED, size, style, color); // the font is registered as truetype font basefont = BaseFont.CreateFont(fontname, encoding, embedded, cached, null, null); } } catch (DocumentException de) { // this shouldn't happen throw de; } catch (System.IO.IOException) { // the font is registered as a true type font, but the path was wrong return new Font(Font.FontFamily.UNDEFINED, size, style, color); } catch { // null was entered as fontname and/or encoding return new Font(Font.FontFamily.UNDEFINED, size, style, color); } return new Font(basefont, size, style, color); } 

Where in this method is it possible that an IEnumerable is changed during an enumeration?

+6
source share
1 answer

Not knowing what is inside your methods, this will prevent your collection from being modified during enumeration:

Edit:

 List<string> tmp; fontFamilies.TryGetValue(lowercasefontname, out tmp); 

To:

 List<string> sharedList; fontFamilies.TryGetValue(lowercasefontname, out sharedList); var tmp = new List<string>(sharedList); 

This will give you a new list, which, as you can be sure, doesn’t access any other thread anywhere, as it is guaranteed to be not just a link to the list in TryGetValue ().

I changed the name of the tmp list from earlier and named the new tmp list, so you won’t need to change any other code.

+8
source

Source: https://habr.com/ru/post/943472/


All Articles