我有一個簡單的服務器客戶端應用程序,使用命名管道。我在服務器中使用StreamWriter,在客戶端使用StreamReader。只要客戶端進程不從管道讀取(即,不從StreamReader讀取,封裝管道),StreamWriter就不會處理。我想明白爲什麼。StreamWriter無法關閉,而其包裹的管道沒有排空?
下面是詳細信息:
這是服務器:
using System;
using System.IO;
using System.IO.Pipes;
class PipeServer
{
static void Main()
{
using (NamedPipeServerStream pipeServer =
new NamedPipeServerStream("testpipe"))
{
Console.Write("Waiting for client connection...");
pipeServer.WaitForConnection();
Console.WriteLine("Client connected.");
try
{
StreamWriter sw = new StreamWriter(pipeServer);
try
{
sw.WriteLine("hello client!");
}
finally
{
sw.Dispose();
}
// Would print only after the client finished sleeping
// and reading from its StreamReader
Console.WriteLine("StreamWriter is now closed");
}
catch (IOException e)
{
Console.WriteLine("ERROR: {0}", e.Message);
}
}
}
}
和這裏的客戶:
using System;
using System.IO;
using System.IO.Pipes;
using System.Threading;
class PipeClient
{
static void Main(string[] args)
{
using (NamedPipeClientStream pipeClient =
new NamedPipeClientStream(".", "testpipe"))
{
Console.Write("Attempting to connect to pipe...");
pipeClient.Connect();
Console.WriteLine("Connected to pipe.");
using (StreamReader sr = new StreamReader(pipeClient))
{
Thread.Sleep(100000);
string temp = sr.ReadLine();
if (temp != null)
{
Console.WriteLine("Received from server: {0}", temp);
}
}
}
}
}
注意的Thread.Sleep(100000);
的客戶:我添加它,以確保只要客戶端進程處於睡眠狀態,StreamWriter就不在服務器中,服務器將不會執行Console.WriteLine("StreamWriter is now closed");
。爲什麼?
編輯:
我切斷其在第二以爲我猜可能是無關緊要的以前的信息。 我還想補充一點 - 感謝Scott在評論中 - 我觀察到這種行爲發生的另一種方式:如果服務器寫入,然後睡眠,客戶端(試圖)用它的StreamReader讀取 - 讀取isn直到服務器醒來纔會發生。
第二個編輯:
另一方向圍繞頭的行爲我在第一編輯談到是無關緊要的,它是一個flush
問題。 我試着給它多一些試驗,並得出了斯科特的權利 - 如果不排水管道不能被處置。那爲什麼?這似乎與StreamWriter
認爲它擁有該流的事實相矛盾,除非另有說明(請參閱here)。
下面是添加細節到上面的代碼:
在服務器程序,該try-finally
現在看起來像這樣:
try
{
sw.AutoFlush = true;
sw.WriteLine("hello client!");
Thread.Sleep(10000);
sw.WriteLine("hello again, client!");
}
finally
{
sw.Dispose(); // awaits while client is sleeping
}
Console.WriteLine("StreamWriter is now closed");
在客戶端程序,所述using
塊現在看起來像這樣:
using (StreamReader sr = new StreamReader(pipeClient))
{
string temp = sr.ReadLine();
Console.WriteLine("blah"); // prints while server sleeps
Console.WriteLine("Received from server: {0}", temp); // prints while server is sleeping
Thread.Sleep(10000);
temp = sr.ReadLine();
Console.WriteLine("Received from server: {0}", temp);
}
請問行爲的改變在所有如果你改變了服務器'新NamedPipeServerStream(「testpipe」,PipeDirection.Out)'和客戶端到'新的NamedPipeClientStream(「。」,「testpipe」,PipeDirection.In)'?另外,如果在讀取之後放置一個'Thread.Sleep(100000);',但仍然在客戶端的'using'中,會發生什麼情況?流在服務器上仍然保持打開狀態,直到它退出使用狀態? –
@ScottChamberlain,根本沒有任何改變,並且改變了'Sleep'的位置是我期望的:服務器進程繼續,打印''StreamWriter現在關閉了''並返回,而客戶端休眠。 – HeyJude
也許它不會讓你關閉,直到緩衝區被耗盡。如果您執行'服務器寫入 - >客戶端讀取 - >服務器寫入 - >服務器處理 - >客戶端讀取',會發生什麼? –