当调试器暂停代码时如何忽略时间的流逝?

Bry*_*ner 5 c# debugging

我正在执行一些计算,如果运行时间太长,我需要超时。我可能会设置 5 秒的超时,并在我的代码中定期进行轮询。实际代码要复杂得多,并且具有大量递归,并且分布在许多类中,但这应该给出它如何工作的一般概念。基本上,任何时候调用递归或执行可能需要时间的操作时,它都会调用 AssertTimeout()。

private DateTime endTime;
public void PerpareTimeout(int timeoutMilliseconds)
{
    endTime = DateTime.UtcNow.AddMilliseconds(timeoutMilliseconds);
}

public void AssertTimeout()
{
    if (DateTime.UtcNow > endTime)
        throw new TimeoutException();
}

public void DoWork1()
{
    foreach (var item in workItems)
    {
        AssertTimeout();
        DoWork2(item)
    }
}
public void DoWork2(WorkItem item)
{
    foreach (var item in workItems)
    {
        AssertTimeout();
        // ...
    }
}
Run Code Online (Sandbox Code Playgroud)

因此,当我连接了调试器并暂停执行时,问题就出现了。我想以某种方式禁用暂停时间的超时。因此,如果它运行了 2 秒,我命中断点并等待 5 分钟,然后恢复,恢复执行后它将再运行 3 秒,然后超时。

我可以使用这样的东西:

public void PrepareTimeout(int timeoutMilliseconds)
{
    if (System.Diagnostics.Debugger.IsDebuggerAttached)
        endTime = DateTime.MaxValue;
    else
        endTime = DateTime.UtcNow.AddMilliseconds(timeoutMilliseconds);
}
Run Code Online (Sandbox Code Playgroud)

但这基本上是在程序在调试环境中运行时给出无限超时,并且如果我不暂停它,我希望它正常超时。

有没有什么方法可以测量经过的时间而不计算调试器暂停所花费的时间?

Bry*_*ner 4

看到Matias Cicero的回答后,我有了一个想法:

如果连接了调试器,则启动一个看门狗线程,该线程除了睡眠之外什么都不做。也许以 100 毫秒为增量。如果程序暂停,对 Thread.Sleep 的调用将花费比预期更长的时间,并且它可以按差值增加结束时间。

public class DebugWatchDog : IDisposable
{
    private bool Terminated;
    private Action<DateTime> updateEndTime;
    private DateTime endTime;
    public DebugWatchDog(Action<DateTime> updateEndTime, DateTime endTime)
    {
        if (!System.Diagnostics.Debugger.IsDebuggerAttached)
            return;
        this.updateEndTime = updateEndTime;
        this.endTime = endTime;
        updateEndTime(DateTime.MaxValue);
        var thread = new Thread(Watch);
        thread.Start();
    }
    public void Dispose()
    {
        lock (this)
            Terminated = true;
    }
    private void Watch()
    {
        DateTime priorTime = DateTime.UtcNow;
        while (true)
        {
            lock (this)
                if (Terminated)
                    return;
            Thread.Sleep(100);
            DateTime nextTime = DateTime.UtcNow;
            var diff = nextTime - priorTime;
            if (diff.TotalMilliseconds > 115)
            {
                endTime += diff;
            }
            if (DateTime.UtcNow > endTime)
            {
                updateEndTime(endTime);
                return;
            }
            priorTime = nextTime;
        }
    }
}
Run Code Online (Sandbox Code Playgroud)