NamedPipeServer.WaitForConnection()函数的行为真的是很霸道,这个函数工作在阻塞模式,而且是不可中断的,也就是说,一旦调用了服务端管道流对象的这个函数,只要没有客户端与之连接,调用线程就会被一只阻塞下去,没有任何办法可以直接中断这个阻塞!要想从这种阻塞中脱离出来,唯一的办法就是在调用线程中创建一个NamedPipeClientStream对象,然后与这个阻塞了线程的NamedPipeServerStream对象建立连接,这样就从阻塞状态脱离出来了。
同样,NamedPipeClientStream.Connect()函数也一样的霸道,在完成与服务端的连接之前,没有任何手段可以直接中断掉该操作,调用线程会被一只阻塞。解决的方法也是在调用线程中创建一个服务端管道流,建立自内部的管道流连接,使得NamedPipeClientStream对象跳出Connect()状态,这样调用线程就可以被中断了。
以下是使用了服务端管道流的线程的代码片段:
class ServerThread
{
public ServerThread(string pipeName)
{
this.pipeName = pipeName;
this.pipedStream = new NamedPipeServerStream(pipeName);
}
public void run()
{
Console.WriteLine(">> SERVER_THREAD: waiting for client connection ...");
pipedStream.WaitForConnection();
Console.WriteLine(" done.");
// 其他操作 ... ...
if (pipedStream != null)
{
shutdownPipedStream();
}
}
public void stop()
{
if (!pipedStream.IsConnected)
{
connectSelf(); // 建立自我链接,以使得服务端管道流跳出WaitForConnection()。
shutdownPipedStream();
}
}
private void shutdownPipedStream()
{
pipedStream.Close();
pipedStream.Dispose();
pipedStream = null;
}
private void connectSelf() // 这个函数用于中断处于WaitForConnection状态的服务端管道流。
// NamedPipeServerStream.WaitForConnection会一直处于阻塞状态直至与客户端管道流建立连接,
// 这个阻塞状态无法被中断!
{
NamedPipeClientStream npcs = new NamedPipeClientStream(pipeName);
npcs.Connect();
}
private String pipeName;
private NamedPipeServerStream pipedStream;
}
以下是主线程代码片段,创建ServerThread对象,并调用其stop方法中断,使得其跳出WaitForConnection状态。
class MultiThreadExchange
{
public void run()
{
Console.Write("creating thread ...");
ServerThread serverThreadInstance = new ServerThread(pipeName);
Thread serverThread = new Thread(new ThreadStart(serverThreadInstance.run));
serverThread.Start();
Console.WriteLine(" done.");
Console.WriteLine("sleeping ...");
Thread.Sleep(waitTime);
Console.WriteLine(" wake up.");
Console.Write("stopping thread ...");
serverThreadInstance.stop();
Console.WriteLine(" done.");
}
private const string pipeName = "testPipe";
private const int waitTime = 3000;
}
运行结果如下:
creating thread ... done.
>> SERVER_THREAD: waiting for client connection ...
sleeping ...
wake up.
stopping thread ... done.
done.
System.NullReferenceException: 未将对象引用设置到对象的实例。
在 LearnCSharpConsole.ServerThread.run() 位置 F:\LJF\program\VCS\WinForm\LearnCSharpGUI\LearnCSharpConsole\MultiThreadExchange.cs:行号 55
中断NamedPipeClientStream.Connect()的代码示例如下:
class ClientThread
{
public ClientThread(string pipeName)
{
this.pipeName = pipeName;
this.pipedStream = new NamedPipeClientStream(pipeName);
}
public void run()
{
Console.Write(">> CLIENT_THREAD: connecting to server pipe stream ...");
pipedStream.Connect();
Console.WriteLine(" done.");
// other processing ...
if (pipedStream != null)
{
stop();
}
}
public void stop()
{
if (!pipedStream.IsConnected)
{
connectSelf();
}
pipedStream.Close();
pipedStream.Dispose();
pipedStream = null;
}
private void connectSelf()
{
NamedPipeServerStream npss = new NamedPipeServerStream(pipeName);
npss.WaitForConnection();
}
private String pipeName;
private NamedPipeClientStream pipedStream;
}