我正在调试一个人工智能机器人,它被输入“重播”输入数据,以使其重播之前进行的比赛。每个回合都限制一定的时间,机器人用该时间来计算当前回合的剩余时间;这让它决定如何使用剩余的周转时间。现在,我想做的是跟踪调试所花费的时间(该回合在断点上花费的总时间),因此我可以将其添加到剩余时间中,以使执行看起来从未暂停.
最初,我尝试使用这样的东西:
private DateTime turnTimeStarted;
public TimeSpan TurnTimeRemaining
{
get { return (turnTimeStarted + TurnTime + TimeSpentInDebugger) -
DateTime.Now; }
}
private DateTime debugStartTime;
private bool inDebugger = false;
private TimeSpan timeSpentInDebugger = new TimeSpan();
public TimeSpan TimeSpentInDebugger
{
get
{
if (!inDebugger)
return timeSpentInDebugger;
return timeSpentInDebugger + (DateTime.Now - debugStartTime);
}
}
public void Break()
{
if (Debugger.IsAttached)
{
debugStartTime = DateTime.Now;
inDebugger = true;
Debugger.Break();
inDebugger = false;
timeSpentInDebugger += DateTime.Now - debugStartTime;
}
}
这样做的问题是,它在实际的
Debugger.Break()
语句而不是 Break()
方法调用上中断,所以我最终超出了我想要调试的代码的上下文。
我正在寻找的是类似于调用
Debugger.Break
之前和之后触发的一组事件,以检测进入和离开断点的时间。有什么办法可以做到这一点吗?
使用秒表 ( http://msdn.microsoft.com/en-us/library/system.diagnostics.stopwatch.aspx ) 类并在中断之前开始,在中断之后停止并根据需要添加时间。
我建议看一下 SlimTune: http://code.google.com/p/slimtune/ 以及 Matt Pietrek 撰写的关于 DNProfiler 的文章 http://msdn.microsoft.com/en-us /杂志/cc301725.aspx
我知道这个话题很旧,但我仍然没有找到更好的解决方案。
关于在错误的上下文中中断,您可以通过公开
Action
属性而不是方法来轻松解决此问题:
public static class MyDebugger {
public static Action Break => Debugger.Break;
}
然后调试器将停止在
MyDebugger.Break()
调用而不是 Debugger.Break
。
您可以在返回操作之前存储时间,但主要问题是您无法判断何时实际恢复执行,因为
Break()
仅请求停止而不是实际执行调试过程。
为了解决这个问题,我编写了一个监视方法,用于测量其执行时间,并在访问属性时在单独的线程上启动它。当执行时间很慢时,将其视为时间花费评估断点,否则,当在一定时间内检测到正常执行速度时,线程退出。
有了这个,你可以这样计算你的时间:
public TimeSpan TurnTimeRemaining
=> turnTimeStarted + TurnTime - Debuger.Now;
问题在于您必须利用整个线程才能获得相当准确的测量结果。当您实际单步执行代码时,这不是什么大问题,但在恢复应用程序后,线程将被阻塞几秒钟。
更重要的是,如果监视器没有持续打开,您将无法检测调试器何时命中 IDE 设置的断点。
为了解决这个问题,我编写了额外的惰性监视器,它以较慢的时间间隔在任务上运行,但它不是那么准确,并且有它自己的问题......
遗憾的是
Debugger
界面太差了。