简体   繁体   English

Sleep(10)什么都不做?

[英]Sleep(10) does nothing?

I have a strange situation with my web service. 我的Web服务遇到一个奇怪的情况。

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. 这是一个简单的例子-它创建了一个持续运行的线程,在后台对磁盘进行了一些磁盘检查,并针对每个文件执行了它存在的工作后进入Sleep(10),因此它不会消耗所有CPU内核。

It all works well, until I log of from RDP. 一切正常,直到我从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). 我有两个核心,我的前台应用使用了大约18%的CPU(这在NOW-meter上显示)。 To the left is the CPU usage when no-one is logged on. 左侧是没有登录时的CPU使用率。

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. 当代码作为Windows服务运行并且没有人连接到计算机时,即使Sleep(1000)也不起作用。 I officially declare it a WTF. 我正式宣布它为WTF。

Don't sleep. 别睡觉 Set your thread priority to IDLE instead. 而是将线程优先级设置为IDLE。

Next thing is to identify the CPU consumption per process , so you don't chase a red herring. 接下来的事情是确定每个进程的CPU消耗,因此您不会追赶红鲱鱼。 Open the Perfmom.exe and look at the Process(*)\\(*) object (all instances). 打开Perfmom.exe并查看Process(*)\\(*)对象(所有实例)。 Then you can inspect the % Processor Time and % User Time for each process and identify who is using the 18% when RDP is closed. 然后,您可以检查每个进程的“ % Processor Time和“ % User Time 并确定在关闭RDP时谁在使用18%的内存。

As a side note, rather than shuffling same directories over and over again , why not use the change notifications mechanism instead? 附带说明shuffling same directories over and over again ,为什么不shuffling same directories over and over again ,为什么不使用更改通知机制呢?

Sleep 10 is only 10 milliseconds -- so you are really close to just yielding and going back to work. 睡眠10仅为10毫秒-因此您真的接近屈服并重新开始工作。

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). 我的猜测是,当您登录时,已经发生了足够的事情,因此您的线程不会立即被重新安排,因此它实际上最终会处于闲置状态超过10毫秒(而且我认为我读到的最大分辨率为睡眠是100米尔,顺便说一句)。 However, when you are not RDP'd, the thread becomes available for rescheduling far more frequently, so it burns more CPU. 但是,当您不使用RDP时,该线程变得可用于更频繁地重新调度,因此它消耗了更多的CPU。

To test, try increasing your sleep duration to 500 (0.5 sec), or 1000, or so, to give you a noticeable sleep period. 要进行测试,请尝试将睡眠时间增加到500(0.5秒)或1000左右,以使您有明显的睡眠时间。

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. 另一个测试是在“什么都不做”循环中丢弃另一个线程,并在强制CPU繁忙时查看您的file.exists线程是否妥善处理。

get spikes like that when I log onto RDP, and I don't have your code running. 当我登录RDP时会遇到类似的高峰,而我没有运行您的代码。 Occam's razor would suggest it's RDP that's making use of the cores. 奥卡姆(Occam)的剃刀暗示它是利用内核的RDP。

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. 此外,如果您正在执行File.Exists,无论如何线程都会在磁盘I / O上阻塞,如果有一个点给CPU带来了沉重负担,那只会在执行完之后才会出现。

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. 最后,如果您还没有做过任何事情,例如从Normal提升进程优先级,那么它将与其他进程共享内核。 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. 如果您拥有多个内核,则对于Windows的最新版本尤其如此。

Edit: Actually, scratch all that. 编辑:其实,全部。 Why poll in a loop yourself rather than in response to a FileSystemWatcher event. 为什么要自己循环轮询而不是响应FileSystemWatcher事件。 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. 设置一个或多个FileSystemWatcher来监视感兴趣的目录,然后轮询您所关心的特定文件存在更改以作为响应。 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. 我现在不需要更改体系结构,并且使用任何数量的Sleep()任何尝试都将失败。 I searched a little other sites besides SO, and found one thread in which Jon Skeet suggests usage of Monitor to signal around. 除了SO之外,我还搜索了其他一些网站,并发现Jon Skeet建议使用Monitor发出信号的一个线程。

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. 这激发了我尝试将AutoResetEventSleep更改为WaitOne的方法,该方法仅用作睡眠的替代方法,在我的情况下,睡眠似乎不起作用。

Tried it, and it worked! 尝试了一下,它起作用了!

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

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