我只是想理解C#中的管道。我有一个简单的LinqPad脚本:
void Main() => Program.Main(null);
// You can define other methods, fields, classes and namespaces here
class Program
{
public static void Main(string[] args)
{
StartServer();
Task.Delay(1000).Wait();
//Client
var client = new NamedPipeClientStream("PipesOfPiece");
client.Connect();
while (true)
{
string input = Guid.NewGuid().ToString();
if (String.IsNullOrEmpty(input)) break;
var someBuffer = new byte[4];
client.Write(someBuffer, 0, someBuffer.Length);
"Client 1st Write".Dump();
client.Write(someBuffer, 0, someBuffer.Length);
"Client 2nd Write".Dump();
client.Read(someBuffer, 0, someBuffer.Length);
"Client 1st Read".Dump();
}
}
static void StartServer()
{
Task.Factory.StartNew(() =>
{
var server = new NamedPipeServerStream("PipesOfPiece");
server.WaitForConnection();
var someBuffer = new byte[4];
while (true)
{
server.Read(someBuffer, 0, someBuffer.Length);
"Server 1st Read".Dump();
server.Write(someBuffer, 0, someBuffer.Length);
"Server 1st Write".Dump();
}
});
}
}
如果运行上面的代码,将得到以下输出:
Client 1st Write
Server 1st Read
因此对client.write
的第二次调用将永远阻塞。有人能解释一下为什么第二次调用write(在同一线程中)会导致管道阻塞吗?
THX
其根本原因是根据同步化上下文和线程切换阻塞问题。像这样做伙计:
public static async Task Main(string[] args)
{
StartServer();
await Task.Delay(1000);
//Client
var client = new NamedPipeClientStream("PipesOfPiece");
await client.ConnectAsync();
while (true)
{
string input = Guid.NewGuid().ToString();
if (String.IsNullOrEmpty(input)) break;
var someBuffer = new byte[4];
await client.WriteAsync(someBuffer, 0, someBuffer.Length);
Console.WriteLine("Client 1st Write");
await client.WriteAsync(someBuffer, 0, someBuffer.Length);
Console.WriteLine("Client 2nd Write");
await client.ReadAsync(someBuffer, 0, someBuffer.Length);
Console.WriteLine("Client 1st Read");
//await Task.Delay(100);
}
}
static void StartServer()
{
Task.Factory.StartNew(async () =>
{
var server = new NamedPipeServerStream("PipesOfPiece");
await server.WaitForConnectionAsync();
var someBuffer = new byte[4];
while (true)
{
await server.ReadAsync(someBuffer, 0, someBuffer.Length);
Console.WriteLine("Server 1st Read");
await server.WriteAsync(someBuffer, 0, someBuffer.Length);
Console.WriteLine("Server 1st Write");
}
});
}