字典的神秘行为(Mysterious behavior of Dictionary)

2019-07-29 12:06发布

我基于Asp.net MVC 3.0和在Mono-2.10.8(Windows 7)中工作的一个庞大的系统上工作。

一切都很好,直到那一刻前两天。

在我的API我有使用字典几个实用程序类。 例如,像这样的:

public static class KeyUtility  
{
  static KeyUtility() {
    Alphabet = new[] {
      'A', 'B', 'C', 'D', 'E', 'F', 'G', 'H', 
      'J', 'K', 'L', 'M', 'N', 'P', 'R', 'S', 
      'T', 'U', 'V', 'X', 'Y', 'Z', '0', '1', 
      '2', '3', '4', '5', '6', '7', '8', '9'
    };

    ReverseAlphabet = Alphabet
      .Select((c, i) => new { Char = c, Value = i })
      .ToDictionary(k => k.Char, v => (byte) v.Value);
  }

  internal static char[] Alphabet;      
  private static IDictionary<char, byte> ReverseAlphabet;

  public static string ToKey(byte[] key, int groupSize)
  {
    //Accessing Alphabet to generate string key from bytes
  }

  public static byte[] FromKey(string key)
  {
    //Accessing ReverseAlphabet to get bytes from string key
  }
}

并随机我得到这样的例外:

System.IndexOutOfRangeException: Array index is out of range.
at System.Collections.Generic.Dictionary`2<char, byte>.TryGetValue (char,byte&) <0x000a1>
at MyAPI.KeyUtility.FromKey (string) <0x0009a>
at MyApp.Controllers.AboutController.Index () <0x002df>
at (wrapper dynamic-method) object.lambda_method (System.Runtime.CompilerServices.Closure,System.Web.Mvc.ControllerBase,object[]) <0x0002f>
at System.Web.Mvc.ActionMethodDispatcher.Execute (System.Web.Mvc.ControllerBase,object[]) <0x0001b>
at System.Web.Mvc.ReflectedActionDescriptor.Execute (System.Web.Mvc.ControllerContext,System.Collections.Generic.IDictionary`2<string, object>) <0x000ff>
at System.Web.Mvc.ControllerActionInvoker.InvokeActionMethod (System.Web.Mvc.ControllerContext,System.Web.Mvc.ActionDescriptor,System.Collections.Generic.IDictionary`2<string, object>) <0x00019>
at System.Web.Mvc.ControllerActionInvoker/<>c__DisplayClass15.<InvokeActionMethodWithFilters>b__12 () <0x00066>
at System.Web.Mvc.ControllerActionInvoker.InvokeActionMethodFilter (System.Web.Mvc.IActionFilter,System.Web.Mvc.ActionExecutingContext,System.Func`1<System.Web.Mvc.ActionExecutedContext>) <0x000b8>

大多数时候,所有的东西都很好, KeyUtility工作正确的,但在少数情况下,我得到这样的例外。 尽管它看起来像线程安全问题,字典ReverseAlphabet总是只,从不读访问以进行写入。 一旦它在静态构造函数创建它只是与访问TryGetValue 。 当我从MSDN文章的理解应该是线程在这种情况下是安全的。 此外,我还没有看到这个问题。

我应该怎么看? 我甚至因为我已经完全不知道什么是错的不能创建再现。

单2.10.8和旧版本被证明是使用词典稳定。 我一直在使用它几年集中之前从来没有见过这种异常。

如何解决这一问题?

UPD:

我记得附近的烦恼开始时我做了什么是静态链接单用我的可执行文件的时间(我嵌入单到我的应用程序)。 我只是下载单的来源。 没有任何变化Compilled它除了我设置libmono的输出到静态库。 我也有libeay32和sqlite3的链接。 所有的多线程(MT)。 也许这个变化可能会影响应用程序? 不幸的是我无法检查该下独立单。 这之前,我是动态链接库,所有的一切都很好。

UPD2:这里是链接到全部的源代码: http://pastebin.com/RU4RNCki

Answer 1:

我做了什么是静态链接单用我的可执行文件

你已经知道我想这个问题,那肯定会打破单。 当你链接它是静态的的DllMain()回调的Windows使得每当一个新的线程启动的过程中执行不再发生的最重要的事情。 这就是CLR如何意识到可以执行托管代码的线程。 静态构造的确是可能的故障模式,线程必须从执行在类的任何代码,直到cctor被阻塞()执行完毕。 在CLR不能做到这一点,如果它不知道该线程。

如果你想使这个工作,那么你至少需要为自己的DllMain()函数mono_thread_info_attach()调用提供一个替代。 在一般情况下,我会说这是一个优化太多。



文章来源: Mysterious behavior of Dictionary