it's possible that I could, though the local variables (that should probably stay local) complicate the refactoring.

I'm able to abandon the more complicated sleep math because running the simple sleep math from a separate thread that communicates over a queue has nearly the same timing characteristics, since a message will be pushed every X seconds to trigger a re-resolve.  I will ensure that a CheckInterval message is only pushed onto an empty queue, as a non-empty queue will trigger a re-resolve ASAP anyway.