TKEY的,TSource>&词典LT神秘的行为; [英] Mysterious behavior of Dictionary<TKey, TSource>

查看:190
本文介绍了TKEY的,TSource>&词典LT神秘的行为;的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

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



一切都很正常,直到片刻夫妇天前。



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

 公共静态类KeyUtility 
{
静态KeyUtility(){
字母=新[] {
'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 =字母
。选择((C,I)=>新建{字符= C,值= I})
.ToDictionary(K => k。 CHAR,v =>(字节)v.Value);
}

内部静态的char []字母;
私有静态的IDictionary<在char,byte> ReverseAlphabet;

公共静态字符串TOKEY(字节[]键,诠释GROUPSIZE)
{
//访问字母来生成字节
串键}

酒店的公共静态的byte [] FROMKEY(字符串键)
{
//访问ReverseAlphabet摆脱串键
字节}
}

和随机我得到的例外是这样的:

  System.IndexOutOfRangeException:数组索引超出范围。 
在System.Collections.Generic.Dictionary`2<在char,byte> .TryGetValue(字符,字节和放大器;)< 0x000a1>
在MyAPI.KeyUtility.FromKey(字符串)< 0x0009a>
在MyApp.Controllers.AboutController.Index()< 0x002df>
在(包装动态法)object.lambda_method(System.Runtime.CompilerServices.Closure,System.Web.Mvc.ControllerBase,对象[])LT; 0x0002f>在System.Web.Mvc.ActionMethodDispatcher.Execute
(System.Web.Mvc.ControllerBase,对象[])LT; 0x0001b> < 0x000ff>在System.Web.Mvc.ReflectedActionDescriptor.Execute(;字符串对象> System.Web.Mvc.ControllerContext,System.Collections.Generic.IDictionary`2<)
; < 0x00019>在System.Web.Mvc.ControllerActionInvoker.InvokeActionMethod(;字符串对象> System.Web.Mvc.ControllerContext,System.Web.Mvc.ActionDescriptor,System.Collections.Generic.IDictionary`2<)
;
在System.Web.Mvc.ControllerActionInvoker /<> c__DisplayClass15< InvokeActionMethodWithFilters> b__12()< 0x00066> < 0x000b8>在System.Web.Mvc.ControllerActionInvoker.InvokeActionMethodFilter(; System.Web.Mvc.ActionExecutedContext> System.Web.Mvc.IActionFilter,System.Web.Mvc.ActionExecutingContext,System.Func`1<)
;



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



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



单声道2.10.8和旧版本被证明是使用词典稳定。我一直在使用它几年深入,还从来没见过这种异常之前的。



如何解决这一问题?



UPD:



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



UPD2:
这里是链接到完整的来源: http://pastebin.com/RU4RNCki


解决方案

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




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



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


I'm working on a huge system based on Asp.net MVC 3.0 and working on Mono-2.10.8 (Windows 7).

Everything was fine until a moment couple of days ago.

Inside my API I have several utility classes using dictionaries. For example, like this one:

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

And randomly I get exceptions like this:

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>

Most of the time everything is fine and KeyUtility works correct, but on rare occasions I get such an exception. Despite it looks like thread safety issue, the dictionary ReverseAlphabet is always accessed for reading only and never for writing. Once it's created in static constructor it's only accessed with TryGetValue. As I understand from MSDN article it should be thread safe in this case. Moreover, I haven't seen this problem before.

What should I look at? I even can't create a reproduction as I have completely no idea what is wrong.

Mono-2.10.8 and older versions proved to be stable with dictionaries. I've been using it for a couple of years intensively and have never seen this sort of exception before.

How to fix this?

UPD:

I've remembered that near the time of the begining of troubles what i've done is statically linked mono with my executable (i'm embedding mono into my application). I simply downloaded sources of mono. Compilled it without any changes except i set up libmono's output to static library. I've also linked with libeay32 and sqlite3. All multithread (MT). Maybe this change could affect an application? Unfortunately i can't check this under standalone mono. Before this i was linking all libraries dynamically and everything was fine.

UPD2: Here is the link to the complete sources: http://pastebin.com/RU4RNCki

解决方案

what i've done is statically linked mono with my executable

You already know the problem I think, that certainly would break mono. The most important thing that doesn't happen anymore when you link it statically is the DllMain() callback that Windows makes whenever a new thread starts executing in the process. That's how the CLR becomes aware of threads that may execute managed code. Static constructors are indeed a likely failure mode, a thread must be blocked from executing any code in the class until the cctor() finished executing. The CLR cannot do this if it doesn't know about the thread.

If you want to make this work then you'll at least need to provide an alternative for the mono_thread_info_attach() call in your own DllMain() function. In general, I'd say this was one optimization too many.

这篇关于TKEY的,TSource&GT;&词典LT神秘的行为;的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
相关文章
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆