8

私は、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 の記事からわかるように、この場合はスレッド セーフである必要があります。さらに、私は以前にこの問題を見たことがありません。

何を見ればいいですか?何が悪いのかわからないので、複製を作成することさえできません。

Mono-2.10.8 およびそれ以前のバージョンは、辞書で安定していることが証明されています。私はそれを数年間集中的に使用してきましたが、この種の例外はこれまで見たことがありません。

これを修正する方法は?

更新:

トラブルが発生する直前に、実行可能ファイルにモノを静的にリンクしたことを思い出しました (アプリケーションにモノを埋め込んでいます)。モノのソースをダウンロードしただけです。libmonoの出力を静的ライブラリに設定する以外は、何も変更せずにコンパイルしました。libeay32 と sqlite3 ともリンクしています。すべてマルチスレッド (MT)。この変更はアプリケーションに影響を与える可能性がありますか? 残念ながら、スタンドアロンのモノではこれを確認できません。この前は、すべてのライブラリを動的にリンクしていましたが、すべて問題ありませんでした。

UPD2: 完全なソースへのリンクは次のとおりです: http://pastebin.com/RU4RNCki

4

1 に答える 1

12

私がやったことは、実行可能ファイルと静的にリンクされたモノです

あなたは私が思う問題をすでに知っています、それは確かにモノを壊すでしょう。静的にリンクしたときにもう発生しない最も重要なことは、プロセスで新しいスレッドの実行が開始されるたびにWindowsが作成するDllMain()コールバックです。これにより、CLRはマネージコードを実行する可能性のあるスレッドを認識します。静的コンストラクターは確かに失敗モードである可能性が高いため、cctor()の実行が終了するまで、スレッドがクラス内のコードを実行するのをブロックする必要があります。CLRは、スレッドについて知らない場合、これを行うことはできません。

これを機能させたい場合は、少なくとも、独自のDllMain()関数でmono_thread_info_attach()呼び出しの代替手段を提供する必要があります。一般的に、これは1つの最適化が多すぎると思います。

于 2012-05-23T13:01:35.330 に答える