Well, what does it do if the minimum time for a frame *hasn't* elapsed yet? If you do a Sleep(0) or something in that case, you should be fine, as you'll yield the rest of your time-slice back to the OS. But if you just sit in a loop and don't do anything that suspends the thread, you'll keep taking up 100% CPU and making it hard for anything else to run.
IMO, the right way to do this is to configure your rendering API to wait for vsync, and if the API is built properly this should suspend the thread until the vsync clears, which will have the side effect of reducing the CPU utilization to a more reasonable level.
For reference, here's my message loop:
while (g_fRendering && PeekMessage(&msg, NULL, 0, 0, true))
if (!GetMessage(&msg, NULL, 0, 0))
The g_fRendering flag gets set to false when you minimize the app, or when it starts shutting down; in that case I use GetMessage, which waits for a message, rather than PeekMessage. Down inside the Render() call I'm eventually calling Present() (since I'm using D3D) and telling it to wait for vsync, which both prevents tearing (usually...) and suspends the thread so that other apps can run.
It's also important to handle *all* available messages after each rendered frame, not just one, hence the PeekMessage in the inner while loop. Otherwise messages can back up and overflow the queue because you don't process them fast enough. Mouse moves especially can generate several messages per frame.