我遇到了命名管道的問題。如果說30個客戶端管道都試圖同時連接到本地管道服務器,在4核心機器上,則會發生超時或信號量超時。有時候,最長的時間,一個客戶端需要一秒鐘才能獲得連接。再下一秒等等。我認爲本地管道訪問應該是快速的。爲什麼30個客戶端 - 即使100個客戶端需要相同的時間 - 也只需要1000毫秒就能建立一個連接?爲什麼命名管道意外地長時間連接到本地管道服務器?
using System;
using System.Diagnostics;
using System.IO.Pipes;
using System.Security.AccessControl;
using System.Threading;
using System.Threading.Tasks;
namespace PipeStress
{
class Program
{
public static PipeSecurity CreatePipeSecurity()
{
PipeSecurity ps;
using (var seedPipe = new NamedPipeServerStream("{DDAB520F-5104-48D1-AA65-7AEF568E0045}",
PipeDirection.InOut, 1, PipeTransmissionMode.Message, PipeOptions.None, 1000, 1000))
{
ps = seedPipe.GetAccessControl();
}
var sid = new System.Security.Principal.SecurityIdentifier(
System.Security.Principal.WellKnownSidType.BuiltinUsersSid, null);
ps.AddAccessRule(new PipeAccessRule(sid, PipeAccessRights.ReadWrite |
PipeAccessRights.CreateNewInstance | PipeAccessRights.ChangePermissions,
AccessControlType.Allow));
sid = new System.Security.Principal.SecurityIdentifier(
System.Security.Principal.WellKnownSidType.LocalServiceSid, null);
ps.AddAccessRule(new PipeAccessRule(sid, PipeAccessRights.ReadWrite,
AccessControlType.Allow));
return ps;
}
static void Main(string[] args)
{
Task.Run(() => RunPipeServer());
for (var i = (uint) 0; i < 30; i++)
{
var index = i;
//Thread.Sleep(100);
Task.Run(() => RunPipeClient(index));
}
Console.ReadLine();
}
private const string PipeName = "{6FDABBF8-BFFD-4624-A67B-3211ED7EF0DC}";
static void RunPipeServer()
{
try
{
var stw = new Stopwatch();
while (true)
{
stw.Restart();
var pipeServer = new NamedPipeServerStream(PipeName, PipeDirection.InOut,
NamedPipeServerStream.MaxAllowedServerInstances,
PipeTransmissionMode.Message, PipeOptions.Asynchronous, 4 * 1024, 4 * 1024,
CreatePipeSecurity());
try
{
var pipe = pipeServer;
pipeServer.WaitForConnection();
Console.WriteLine(stw.ElapsedMilliseconds + "ms");
Task.Run(() => HandleClient(pipe));
}
catch (Exception ex)
{
pipeServer.Dispose();
}
}
}
catch (Exception ex)
{
Console.WriteLine(ex);
}
}
private static void HandleClient(NamedPipeServerStream pipeServer)
{
try
{
try
{
//Thread.Sleep(100);
}
finally
{
pipeServer.Close();
}
}
finally
{
pipeServer.Dispose();
}
}
static void RunPipeClient(uint i)
{
try
{
var j = 0;
while (true)
{
using (var pipeClient = new NamedPipeClientStream(".", PipeName, PipeDirection.InOut, PipeOptions.None))
{
//Thread.Sleep(100);
pipeClient.Connect(5000);
try
{
Console.WriteLine($"{i}, {++j}");
pipeClient.ReadByte();
}
finally
{
pipeClient.Close();
}
}
}
}
catch (Exception ex)
{
Console.WriteLine(ex);
}
}
}
}
非常感謝您的回覆。這非常有幫助和啓發。 – PieterB