2

我正在用 c# 编写一个 .net 紧凑型框架应用程序。它在开发环境中运行良好,但是当以发布模式构建并自行运行时,它会抛出 MethodNotFound 异常。我撒了一堆调试日志代码来找出它在哪里被破坏并将其缩小到一个大的 Init() 函数。这反过来又调用了几个单例类的方法,这些类的实现如下:

private SingletonClass() {}

private static readonly SingletonClass _instance = new SingletonClass();
public static SingletonClass Instance
{
 get
 {
  return _instance;
 }
}

我注意到的一件事是,来自单例类中构造函数的调试条目将在 Init() 函数的第一个条目之前记录。看起来运行时引擎在实际开始运行我的代码之前正在做一些事情。

一旦我在这些单例类中拥有“足够”的调试代码,它就不会抛出 MethodNotFound 异常,并且程序会运行得很好。我说“够了”是因为我可以注释掉调试代码并获得 MethodNotFound。当我再次取消评论时,它起作用了。

奇怪的是,当没有抛出异常时,调试日志条目将按照我的代码调用它们的顺序排列。这几乎就像运行时引擎没有像抛出 MethodNotFound 时那样做它的“幕后”工作。

我尝试清除具有单例类的项目上的“优化代码”选项,它似乎已经解决了这个问题。(我一开始尝试了这个,但很难学到 UI 项目上的项目选项不会影响业务逻辑项目。)

我确实发现的一些关于 MethodNotFound 的帖子谈到了缺少 DLL、错误的 DLL 版本或内存不足。

我确实找到了一篇关于编译器如何处理单例类中使用的静态内容的帖子。

http://www.yoda.arachsys.com/csharp/singleton.html

我认为这与我遇到的问题有关,但最后我必须清除“优化代码”才能使其正常工作。

所以我的问题是到底发生了什么?它正在起作用,所以目前这是一个学术问题。希望这可以避免其他人的头痛。

4

1 回答 1

2

您是否在代码中的任何地方使用反射来遍历调用堆栈?(搜索 StackFrame 或 StackTrace 类)

优化代码时通常会内联小函数,这意味着特定方法可能会在发布版本中完全从调用堆栈中消失。如果您希望该方法存在于调用堆栈中,您可能会看到内联。

当您将调试代码添加到一个小函数时,我猜测 JIT 停止将其判断为可内联函数,因此该方法返回调用堆栈,您的问题就消失了。

您可以使用CompilerServices.MethodImpl属性将方法标记为不可内联。尝试将其应用于通过添加调试代码“修复”的功能之一。

另请参阅 http://blogs.msdn.com/davidnotario/archive/2004/11/01/250398.aspx

于 2010-01-11T14:02:26.420 回答