我编写了一个运行线程的服务,该线程每分钟设置一次设置。
该服务按预期执行,但后来发现它使CPU使用率非常高(双核上约为25%)。
使用反复试验我发现以下对象导致了问题:
private AsyncPipes.NamedPipeStreamServer pipeServer = new NamedPipeStreamServer("NotifyToService");
private AsyncPipes.NamedPipeStreamClient pipeClient = new NamedPipeStreamClient("ServiceToNotify");
命名管道使用如此多的CPU是否正常,只是通过实例化?
答案 0 :(得分:5)
我可以复制你的结果(我的8核CPU只有13%)。我必须从this article的末尾下载并构建AsyncPipes库。问题是NamedPipeStreamClient
中的代码每秒抛出一次System.TimeoutException
。
以一种糟糕的设计方式,NamedPipeStreamClient
的构造函数在设置了一些类成员后调用了一个名为StartTryConnect()
的方法。
该方法反过来启动一个调用方法TryConnect
的后台线程。它在这里进入了一个紧密的循环:
while (!this._Stream.IsConnected)
{
try
{
((NamedPipeClientStream) this._Stream).Connect(0x3e8);
}
catch
{
}
}
在您的客户端尝试连接的服务器(“ServiceToNotify”)实际启动之前,情况就是如此。但是,我没有看到任何名称的命名管道服务器(你有相反的,“NotifyToService”)启动的地方。
但是,一旦连接到服务器,CPU使用率将按预期下降。
答案 1 :(得分:1)
这是我最终用来避免这个问题。它是此MSDN论坛帖子中显示的解决方案的简化版本:
[return: MarshalAs( UnmanagedType.Bool )]
[DllImport( "kernel32.dll", CharSet=CharSet.Unicode, SetLastError=true )]
private static extern bool WaitNamedPipe( string name, int timeout );
/// <summary>
/// Method to test if Windows considers that a named pipe of a certain name exists or not.
/// </summary>
internal static bool DoesNamedPipeExist(string pipeFileName)
{
try
{
return WaitNamedPipe(@"\\.\pipe\" + pipeFileName, 0);
}
catch (Exception)
{
return false;
}
}
这是使用NamedPipeClientStream.Connect()方法的地方的一些代码:
// If necessary, wait for the server end to open the named pipe. Otherwise the following
// NamedPipeClientStream.Connect() method can burn up 100% CPU time while waiting for
// the connection.
while (true)
{
if (DoesNamedPipeExist(_pipeFileName))
break;
Thread.Sleep(1000);
}
// Connect to named pipe server - this is a blocking call, and in fact is a blocking
// call that can use 100% CPU time while waiting for a connection
_namedPipeClient.Connect();
答案 2 :(得分:-2)
除非服务在某个时刻睡觉/等待,否则这是完全正常的行为。默认情况下,while true{}
循环将使用其执行位置的100%处理能力。 25%听起来很像您计算机上可用的4个线程中的1/4。
您实际上想在编码时使用100%的CPU,否则为什么要为更快的计算机付费?...