2013-04-23 10 views
6

私はSystem.InvalidOperationException: Collection was modified; enumeration operation may not executeを取得しています:`System.InvalidOperationExceptionが発生しました:コレクションが変更されました。列挙操作は、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) 
[...] 

私が理解からのIEnumerableオブジェクトはその列挙中に変更された場合、その例外が発生します。

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); 
    } 

その方法では、それはIEnumerableをオブジェクトが列挙中に変更されている可能性がある:

ここiTextSharp.text.FontFactoryImp.GetFont方法はありますか?あなたのメソッド内にあるものを知らず、これは列挙中に変更されることから、あなたのコレクションを防ぐことができます

+8

このコードは、このメソッドがコレクションをまったく変更していないため、別のスレッドがコレクションを変更しているようです。あなたの問題はあなたのコードのどこかにあります。 – Servy

+1

変更されたコレクションがtmpの場合、リストが返されたときにディープコピーを作成して、別の場所で変更されることを心配する必要はありません。 – Chris

+0

@CLandry、私のライブラリではありません。私はちょうどそれの底に到達しようとしています。 – mattalxndr

答えて

8

変更:

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

へ:

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

これはあなたを与えるだろうTryGetValue()のリストへの参照だけでなく、他のスレッドによってアクセスされていないことが確実な新しいリストです。

私は以前からtmpリストの名前を変更し、他のコードを変更する必要がないように新しいリストtmpという名前を付けました。

関連する問題