简体   繁体   中英

Sleep(10) does nothing?

I have a strange situation with my web service.

It is a simple one - it creates a Thread that runs constantly, doing some disk checks in the background, and for every File.Exists that it performs, it goes into Sleep(10) so it doesn't consume ALL of the CPU core.

It all works well, until I log of from RDP. When I do that, this thread will spike and consume as much as it can.

Here, have a look-see...

I have two cores, and my foreground app is using about 18% CPU (whis is shown on the NOW-meter). To the left is the CPU usage when no-one is logged on.

What is going on? And more - what to do to throttle the Thread appropriately under this circumstance?

在此处输入图片说明

My code snippet that produces the issue:

foreach (string fi in files)
{
    if (_shouldStop)
    {
        break;
    }
    lock (_workItems)
    {
        StatusString = string.Format("Examining file Dir={0}\nmask={1}\nfile={2}\nqueue={3}",
            root, mask, fi, _workItems.Count);
    }
    lock (_workItems)
    {
        if (!_workItems.Contains(fi))
        {
            if (!File.Exists(TargetForFile(fi + ".hash")))
            {
                StatusString = string.Format("Adding file Dir={0}\nmask={1}\nfile={2}\nqueue={3}",
                root, mask, fi, _workItems.Count);
                _workItems.Add(fi);
            }
        }
    }
    Thread.Sleep(10);
}

Small update:

Even Sleep(1000) does NOTHING when code is run as windows service and no-one is connected to the machine. I officially declare it a WTF.

Don't sleep. Set your thread priority to IDLE instead.

Next thing is to identify the CPU consumption per process , so you don't chase a red herring. Open the Perfmom.exe and look at the Process(*)\\(*) object (all instances). Then you can inspect the % Processor Time and % User Time for each process and identify who is using the 18% when RDP is closed.

As a side note, rather than shuffling same directories over and over again , why not use the change notifications mechanism instead?

Sleep 10 is only 10 milliseconds -- so you are really close to just yielding and going back to work.

My guess would be that when you are logged on, there is enough going on that your thread doesn't get rescheduled immediately, so that it really ends up being inactive for more than 10 milliseconds (and I think I read that the max resolution of the sleep is 100 mills, btw). However, when you are not RDP'd, the thread becomes available for rescheduling far more frequently, so it burns more CPU.

To test, try increasing your sleep duration to 500 (0.5 sec), or 1000, or so, to give you a noticeable sleep period.

Another test, would be to throw down another thread in a do-nothing loop and see if your file.exists thread yields respectfully when you are forcing the CPU to be busy.

get spikes like that when I log onto RDP, and I don't have your code running. Occam's razor would suggest it's RDP that's making use of the cores.

Besides, if you're doing File.Exists, the thread's going to be blocking on disk I/O anyway, if there's a point where it's putting a serious burden on the CPU, it won't be when it's just done that.

Finally, if you haven't done anything nuts like up the process priority from Normal, then it's going to share the cores with other processes anyway. It might be a bit bad if it falls into a tight loop, but even then the scheduler should prevent it doing too much harm on its own. All the more so with the more recent versions of Windows, and if you have more than one core.

Edit: Actually, scratch all that. Why poll in a loop yourself rather than in response to a FileSystemWatcher event. Set one or more FileSystemWatcher s to watch directory(s) of interest, and then poll for the specific file existence changes you care about in response to that. Less work for the code, and should be more responsive too.

Thank you for all the answers provided, but I'll try to provide one of my own.

I don't need architecture change at this point, and any attempts to use any amount of Sleep() failed. I searched a little other sites besides SO, and found one thread in which Jon Skeet suggests usage of Monitor to signal around.

This inspired me to try and change the Sleep to WaitOne of AutoResetEvent , which I'll use only as alternative to sleeping which, as it seems, doesn't work under my circumstances.

Tried it, and it worked!

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM