Monotouch崩溃字典FirstOrDefault()类型Initializer PredicateOf

时间:2011-06-29 08:30:49

标签: c# iphone xamarin.ios aot

经过2周的开发后,我首先在iphone上尝试了我的应用程序,它在以下行崩溃(在模拟器中完美运行):

我有以下代码:

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

希望有人知道该怎么做。

感谢

3 个答案:

答案 0 :(得分:2)

不知何故,AOT编译器无法检测到这种情况,所以是的,您应该提交有关它的错误报告。与此同时,您可以通过以下方式解决此问题:

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

这将避免在执行完全相同的事情(执行明智)时达到PredicateOf并且比循环自己更短。

你也得到了一个TypeLoadException,因为原始异常发生在静态构造函数中(它总是导致TLE,内部异常应该是你期望看到的异常)。

更新:这是以bug #300提交并在最新版本的MonoTouch(4.2 +)中修复

答案 1 :(得分:0)

可能,因为静态编译器无法确定字典中对FirstOrDefault的调用是否需要编译PredicateOf。

答案 2 :(得分:0)

将静态构造函数和新的AOTHint()静态方法添加到包含Processqueue()方法的类中。在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()中指定和调用的类型。

对于每个有问题方法的类,针对每种问题类型执行此操作,并且从现在到Mono计算出如何使其通用编译减少错误时,您的担忧将会消失。

这可以确保AOT编译器确切地知道您需要什么,以极少的成本浪费地创建一些空的通用对象,并在应用程序启动时调用它们上的一些LINQ方法。