heinzler
heinzler

Reputation: 35

Monotouch crash dictionary FirstOrDefault() Type Initializer PredicateOf

after 2 Weeks of Developement i first tried my app on the iphone and it crashes at the following line (which works perfectly in the simulator):

i have the following code:

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

Hope that someone has an idea what to do.

thanks

Upvotes: 1

Views: 774

Answers (3)

Slipp D. Thompson
Slipp D. Thompson

Reputation: 34943

Add a static constructor and a new AOTHint() static method to the class that contains the Processqueue() method.  In AOTHint(), create a fresh instance of the specific generic class you're having trouble with, and call the method it's having trouble with.

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

Note: I haven't tried running your specific code with the above in MonoTouch; this is an adapted solution from what I've used a number of times before for “Attempting to JIT compile method” issues.  If this doesn't work, you'll likely need to play with the types specified and called in AOTHint().

Do this for each class that has problem methods, for each of the problem types, and your worries will be gone in the time between now and whenever the Mono figures out how to make their generic compilation less-buggy.

This works by making sure the AOT compiler knows exactly what you need, at the minimal cost of wastefully creating a handful empty generic objects and calling a handful of LINQ methods on them at app launch time.

Upvotes: 0

poupou
poupou

Reputation: 43553

Somehow the AOT compiler could not detect this case so yes you should file a bug report about it. In the mean time you can workaround this by doing:

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

which will avoid reaching PredicateOf while doing the exact same thing (execution wise) and a bit shorter than looping yourself.

Also you got a TypeLoadException because the original exception occurred in a static constructor (which always results in a TLE, the inner exception should be the one you expected to see).

UPDATE: This was filed as bug #300 and fixed in recent releases of MonoTouch (4.2+)

Upvotes: 2

miguel.de.icaza
miguel.de.icaza

Reputation: 32694

Likely, because the static compiler could not determine that the call to FirstOrDefault in the dictionary will require the compilation of PredicateOf.

Upvotes: 0

Related Questions