【发布时间】:2012-03-12 16:01:59
【问题描述】:
看起来我有一个 JIT 错误(另一个:/):
我有这段代码:
private Boolean m_bIsLoaded = false;
public Boolean IsLoaded
{
get { return this.m_bIsLoaded; }
set { this.m_bIsLoaded = value; }
}
public long DocGedCourrier {
get {
if ((this.IsLoaded == false)) {
this.Load();
}
return this.GetInt64Value("ID_DOCGEDCOURRIER");
}
set {
this.SetValue("ID_DOCGEDCOURRIER", value);
NotifyPropertyChanged("DocGedCourrier");
}
}
我正在调试的 x64 平台(Windows XP Service Pack 3)上运行 Windows 服务,没有进行优化。
当我远程连接调试器并在 this.Load() 方法上放置断点时,调试器停止。如果我查看 this.IsLoaded 的值,它会返回 True。
如果我在未附加调试器的情况下运行服务,则始终调用 Load() 函数,即使 IsLoaded == True。
如果我在附加调试器的情况下运行服务,则在我逐步调试时不会调用 Load()。
如果我在 x86 平台(Windows XP Service Pack 3)上运行该服务,无论是否连接调试器,它都能完美运行。
m_bIsLoaded 无法更改,因为 m_bIsLoaded 仅使用 IsLoaded 属性和 set { this.m_bIsLoaded = value; 设置。 } 只调用一次,IsLoaded = true。
我 99.99% 确定这是 JIT 错误,因为我已经遇到过这种问题(另请参阅 Variable is not incrementing in C# Release x64)。
我的问题是:
我怎样才能发现这种问题并绝对避免它们?
谢谢,
编辑:
我添加了一个锁以确保 IsLoaded 不会被另一个线程修改:
public readonly Object Lock = new Object();
public virtual Object Load()
{
lock (Lock)
{
if ((IsLoaded))
{
return this;
}
}
...
}
public Boolean IsLoaded
{
get { return this.m_bIsLoaded; }
set
{
lock (Lock)
{
this.m_bIsLoaded = value;
}
}
}
它没有解决问题。正如您在此屏幕截图中看到的那样:http://img15.hostingpics.net/pics/125986Screenshoot.jpg。返回 this is not call 即使 IsLoaded 设置为 True。
我排除了多线程访问的可能性。顺便说一句,IsLoaded 仅在字段初始化时设置为 false。如果 IsLoaded 为 True,我的代码中就不可能再有 False 值。
我能做些什么来防止这种情况发生?
【问题讨论】:
-
尝试在 IsLoaded 属性的 set 部分设置断点。当调试器停止时,查看您的堆栈窗口以找出谁在调用该属性
-
正如我所提到的,该集合只被调用一次。我使用断点检查了这一点。分配的值为 True。之后,如果通过,即使 IsLoaded 返回 True。
-
您确定这不是可见性问题,即 m_BIsLoaded 字段是否仅由同一线程访问/修改?
-
False 永远不会分配给 m_bIsLoaded 或 IsLoaded。唯一的错误分配是在 m_bIsLoaded 的声明中。
-
@Filimindji,确保二进制文件是正确的(只是为了偏执——你将它作为服务运行,所以二进制文件可能是旧的)。向构造函数和 Load 方法添加跟踪语句,记录完整的调用堆栈并确保跟踪输出到文件 - 可能会显示一些有用的东西。