2011-06-29 5 views
1

を入力します。私は、次のコードを持っているMonoTouchでクラッシュ辞書FirstOrDefault()私が最初にiphoneに私のアプリを試してみましたが、それは次の行(シミュレータで完璧に動作します)でクラッシュし開発効率向上の2週間後に初期化子PredicateOf

private readonly Dictionary<string, QueueItem queued = new Dictionary<string, QueueItem>(); 

private void Processqueue() 
{ 
    KeyValuePair<string, QueueItem> valuePair = queued.FirstOrDefault(); 
    // Crashes with: System.TypeInitializationException has been thrown 
    // "And exception was thrown by the type initializer for PredicateOf`1" 
} 

private class QueueItem 
{ 
    public string Url { get; set; } 
    public Action<string> ImageLoaded { get; set; } 
    public bool Pending { get; set; } 
} 

誰かが何をすべきか考えていることを願っています。

おかげ

+0

列挙子コード を使用してこの問題を回避することができました。var enumerator = queued.GetEnumerator(); if(enumerator.MoveNext()){.. eumerator.Curent; } しかし、linq構文がクラッシュする理由を知ることは興味深いでしょう。 – heinzler

答えて

2

何とかAOTコンパイラがこのケースを検出できなかったので、バグレポートを提出する必要があります。平均時間では、あなたが行うことでこの問題を回避することができます

KeyValuePair<string, QueueItem> valuePair = queued.FirstOrDefault (delegate { return true; }); 

をまったく同じこと(実行賢明)と自分をループより短いビットをしながらPredicateOfに到達しないようであろう。

また、元の例外が静的なコンストラクタで発生したため、TypeLoadExceptionが発生しました(常にTLEが発生しますが、内部の例外は表示されるはずです)。

UPDATE:これはbug #300として提出し、MonoTouchでの最近のリリースで修正されました(4.2 +)

+0

しかし、それはシミュレータでなぜ機能しますか? – CodesInChaos

+0

シミュレータにはJITの制限がありません。実際には速い(ビルド時間)シミュレータビルドはAOTを使用せず、通常のJITを使用します。 – poupou

0

多分、静的コンパイラが辞書にFirstOrDefaultへの呼び出しがPredicateOfのコンパイルを必要とすることを決定できなかったため。

+0

これはバグとして宣言できますか?私はSingleOrDefault ()はPredicateOf を使用するので、なぜ静的コンパイラは知らないのですか? 興味深いことに、この例外は他の失敗とは異なります。通常、いくつかのlinqを使用するとJIT例外が発生します。 – heinzler

+0

この問題は修正され、MonoTouchの新しいリリースの一部になります。同様の問題がある場合は、bugzilla.xamarin.comに報告してください(テストケースとともに)。ありがとう! – poupou

0

Processqueue()メソッドを含むクラスの静的コンストラクタと新しいAOTHint()静的メソッドを追加します。 AOTHint()では、問題が発生している特定の汎用クラスの新しいインスタンスを作成し、問題のあるメソッドを呼び出します。

static MyClass() { 
    AOTHint(); 
} 

static void AOTHint() 
{ 
    // @fixes: ExecutionEngineException: Attempting to JIT compile method 'System.Collections.Generic.Dictionary`1.FirstOrDefault()' while running with --aot-only. 
    (new Dictionary<string, QueueItem>()).FirstOrDefault(); 
} 

注:私はMonoTouchで上記で特定のコードを実行しようとしていません。これは、 "JITコンパイル方法の試行"の問題のために私が何回も前から使用してきたものからの適合した解決策です。これでうまくいかない場合は、指定された種類のゲームをプレイする必要があります。AOTHint()で呼び出されます。

は、問題のタイプごとに、問題のメソッドを持つクラスごとにこれを行うには、あなたの悩みは今といつでもモノは彼らの一般的なコンパイルあまりバギーを作る方法を割り出し間の時間で消えてしまいます。

これは、AOTコンパイラが必要なものを正確に知っていることを確認することで、一握りの空の汎用オブジェクトを無駄に作成し、アプリ起動時に少数のLINQメソッドを呼び出すというコストを最小限に抑えます。

関連する問題