服务中的命名管道导致高CPU使用率

时间:2013-06-19 14:13:36

标签: c#

我编写了一个运行线程的服务,该线程每分钟设置一次设置。

该服务按预期执行,但后来发现它使CPU使用率非常高(双核上约为25%)。

使用反复试验我发现以下对象导致了问题:

private AsyncPipes.NamedPipeStreamServer pipeServer = new NamedPipeStreamServer("NotifyToService");
private AsyncPipes.NamedPipeStreamClient pipeClient = new NamedPipeStreamClient("ServiceToNotify");

命名管道使用如此多的CPU是否正常,只是通过实例化?

3 个答案:

答案 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论坛帖子中显示的解决方案的简化版本:

https://social.msdn.microsoft.com/Forums/en-US/7bbf5a0b-3c22-4836-b271-999e514c321b/namedpipeclientstreamconnect-causes-cpu-hang-is-there-a-workaround

  [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,否则为什么要为更快的计算机付费?...