diff --git a/NamedPipeWrapper/NamedPipeClient.cs b/NamedPipeWrapper/NamedPipeClient.cs index a1132c5..c817065 100644 --- a/NamedPipeWrapper/NamedPipeClient.cs +++ b/NamedPipeWrapper/NamedPipeClient.cs @@ -1,8 +1,5 @@ using System; -using System.Collections.Generic; using System.IO.Pipes; -using System.Linq; -using System.Text; using System.Threading; using NamedPipeWrapper.IO; using NamedPipeWrapper.Threading; @@ -16,11 +13,11 @@ namespace NamedPipeWrapper public class NamedPipeClient : NamedPipeClient where TReadWrite : class { /// - /// Constructs a new NamedPipeClient to connect to the specified by . + /// Constructs a new NamedPipeClient to connect to the specified by . /// /// Name of the server's pipe /// server name default is local. - public NamedPipeClient(string pipeName,string serverName=".") : base(pipeName, serverName) + public NamedPipeClient(string pipeName, string serverName = ".") : base(pipeName, serverName) { } } @@ -46,6 +43,11 @@ public class NamedPipeClient /// public event ConnectionMessageEventHandler ServerMessage; + /// + /// Invoked when the client connects to the server. + /// + public event ConnectionEventHandler Connected; + /// /// Invoked when the client disconnects from the server (e.g., the pipe is closed or broken). /// @@ -69,11 +71,11 @@ public class NamedPipeClient private string _serverName { get; set; } /// - /// Constructs a new NamedPipeClient to connect to the specified by . + /// Constructs a new NamedPipeClient to connect to the specified by . /// /// Name of the server's pipe /// the Name of the server, default is local machine - public NamedPipeClient(string pipeName,string serverName) + public NamedPipeClient(string pipeName, string serverName) { _pipeName = pipeName; _serverName = serverName; @@ -92,14 +94,34 @@ public void Start() worker.DoWork(ListenSync); } + /// + /// Connects to the named pipe server synchronously. + /// + /// + public void StartSynchronously() + { + _closedExplicitly = false; + try + { + ListenSync(); + } + catch (Exception e) + { + OnError(e); + } + } + /// /// Sends a message to the server over a named pipe. /// /// Message to send to the server. - public void PushMessage(TWrite message) + /// false if conection is null + public bool PushMessage(TWrite message) { - if (_connection != null) - _connection.PushMessage(message); + if (_connection == null) return false; + + _connection.PushMessage(message); + return true; } /// @@ -113,35 +135,62 @@ public void Stop() } #region Wait for connection/disconnection - - public void WaitForConnection() + /// + /// Wait for connection + /// + /// true if connected + public bool WaitForConnection() { - _connected.WaitOne(); + return _connected.WaitOne(); } - public void WaitForConnection(int millisecondsTimeout) + /// + /// Wait for connection + /// + /// + /// true if connected + public bool WaitForConnection(int millisecondsTimeout) { - _connected.WaitOne(millisecondsTimeout); + return _connected.WaitOne(millisecondsTimeout); } - public void WaitForConnection(TimeSpan timeout) + /// + /// Wait for connection + /// + /// + /// true if connected + public bool WaitForConnection(TimeSpan timeout) { - _connected.WaitOne(timeout); + return _connected.WaitOne(timeout); } - public void WaitForDisconnection() + /// + /// Wait for disconnection + /// + /// true if disconnected + public bool WaitForDisconnection() { - _disconnected.WaitOne(); + return _disconnected.WaitOne(); } - public void WaitForDisconnection(int millisecondsTimeout) + /// + /// Wait for disconnection + /// + /// + /// true if disconnected + public bool WaitForDisconnection(int millisecondsTimeout) { - _disconnected.WaitOne(millisecondsTimeout); + return _disconnected.WaitOne(millisecondsTimeout); } - public void WaitForDisconnection(TimeSpan timeout) + /// + /// Wait for disconnection + /// + /// + /// true if disconnected + public bool WaitForDisconnection(TimeSpan timeout) { - _disconnected.WaitOne(timeout); + return _disconnected.WaitOne(timeout); } #endregion @@ -151,12 +200,12 @@ public void WaitForDisconnection(TimeSpan timeout) private void ListenSync() { // Get the name of the data pipe that should be used from now on by this NamedPipeClient - var handshake = PipeClientFactory.Connect(_pipeName,_serverName); + var handshake = PipeClientFactory.Connect(_pipeName, _serverName); var dataPipeName = handshake.ReadObject(); handshake.Close(); // Connect to the actual data pipe - var dataPipe = PipeClientFactory.CreateAndConnectPipe(dataPipeName,_serverName); + var dataPipe = PipeClientFactory.CreateAndConnectPipe(dataPipeName, _serverName); // Create a Connection object for the data pipe _connection = ConnectionFactory.CreateConnection(dataPipe); @@ -166,6 +215,9 @@ private void ListenSync() _connection.Open(); _connected.Set(); + + if (Connected != null) + Connected(_connection); } private void OnDisconnected(NamedPipeConnection connection) @@ -209,11 +261,11 @@ private void OnError(Exception exception) static class PipeClientFactory { - public static PipeStreamWrapper Connect(string pipeName,string serverName) + public static PipeStreamWrapper Connect(string pipeName, string serverName) where TRead : class where TWrite : class { - return new PipeStreamWrapper(CreateAndConnectPipe(pipeName,serverName)); + return new PipeStreamWrapper(CreateAndConnectPipe(pipeName, serverName)); } public static NamedPipeClientStream CreateAndConnectPipe(string pipeName, string serverName) @@ -223,7 +275,7 @@ public static NamedPipeClientStream CreateAndConnectPipe(string pipeName, string return pipe; } - private static NamedPipeClientStream CreatePipe(string pipeName,string serverName) + private static NamedPipeClientStream CreatePipe(string pipeName, string serverName) { return new NamedPipeClientStream(serverName, pipeName, PipeDirection.InOut, PipeOptions.Asynchronous | PipeOptions.WriteThrough); } diff --git a/NamedPipeWrapper/NamedPipeConnection.cs b/NamedPipeWrapper/NamedPipeConnection.cs index 1894718..ffdd1d4 100644 --- a/NamedPipeWrapper/NamedPipeConnection.cs +++ b/NamedPipeWrapper/NamedPipeConnection.cs @@ -1,16 +1,13 @@ using System; -using System.Collections.Generic; using System.IO.Pipes; -using System.Linq; using System.Runtime.Serialization; -using System.Text; using System.Threading; using NamedPipeWrapper.IO; using NamedPipeWrapper.Threading; using System.Collections.Concurrent; namespace NamedPipeWrapper -{ +{ /// /// Represents a connection between a named pipe client and server. /// @@ -162,8 +159,8 @@ private void ReadPipe() { //we must igonre exception, otherwise, the namepipe wrapper will stop work. } - } - + } + } /// @@ -171,26 +168,26 @@ private void ReadPipe() /// /// An object in the graph of type parameter is not marked as serializable. private void WritePipe() - { - - while (IsConnected && _streamWrapper.CanWrite) + { + + while (IsConnected && _streamWrapper.CanWrite) + { + try + { + //using blockcollection, we needn't use singal to wait for result. + //_writeSignal.WaitOne(); + //while (_writeQueue.Count > 0) + { + _streamWrapper.WriteObject(_writeQueue.Take()); + _streamWrapper.WaitForPipeDrain(); + } + } + catch { - try - { - //using blockcollection, we needn't use singal to wait for result. - //_writeSignal.WaitOne(); - //while (_writeQueue.Count > 0) - { - _streamWrapper.WriteObject(_writeQueue.Take()); - _streamWrapper.WaitForPipeDrain(); - } - } - catch - { //we must igonre exception, otherwise, the namepipe wrapper will stop work. } - } - + } + } } diff --git a/NamedPipeWrapper/NamedPipeServer.cs b/NamedPipeWrapper/NamedPipeServer.cs index cae2bc0..e41e116 100644 --- a/NamedPipeWrapper/NamedPipeServer.cs +++ b/NamedPipeWrapper/NamedPipeServer.cs @@ -2,10 +2,10 @@ using NamedPipeWrapper.Threading; using System; using System.Collections.Generic; -using System.IO.Pipes; - +using System.IO.Pipes; + namespace NamedPipeWrapper -{ +{ /// /// Wraps a and provides multiple simultaneous client connection handling. /// @@ -25,6 +25,7 @@ public NamedPipeServer(string pipeName) /// Constructs a new NamedPipeServer object that listens for client connections on the given . /// /// Name of the pipe to listen on + /// public NamedPipeServer(string pipeName, PipeSecurity pipeSecurity) : base(pipeName, pipeSecurity) { @@ -67,12 +68,12 @@ public class Server private int _nextPipeId; private volatile bool _shouldKeepRunning; - private volatile bool _isRunning; /// /// Constructs a new NamedPipeServer object that listens for client connections on the given . /// /// Name of the pipe to listen on + /// public Server(string pipeName, PipeSecurity pipeSecurity) { _pipeName = pipeName; @@ -153,12 +154,10 @@ public void Stop() private void ListenSync() { - _isRunning = true; while (_shouldKeepRunning) { WaitForConnection(_pipeName, _pipeSecurity); } - _isRunning = false; } private void WaitForConnection(string pipeName, PipeSecurity pipeSecurity) diff --git a/UnitTests/SerializableTests.cs b/UnitTests/SerializableTests.cs index 61765cb..dbdf651 100644 --- a/UnitTests/SerializableTests.cs +++ b/UnitTests/SerializableTests.cs @@ -35,7 +35,6 @@ static SerializableTests() private int _expectedHash; private TestCollection _actualData; private int _actualHash; - private bool _clientDisconnected; private DateTime _startTime; @@ -60,7 +59,6 @@ public void SetUp() _expectedHash = 0; _actualData = null; _actualHash = 0; - _clientDisconnected = false; _server.ClientMessage += ServerOnClientMessage; @@ -137,7 +135,7 @@ public void TestCircularReferences() Assert.NotNull(_actualHash, string.Format("Server should have received client's {0} item message", _expectedData.Count)); Assert.AreEqual(_expectedHash, _actualHash, string.Format("Hash codes for {0} item message should match", _expectedData.Count)); Assert.AreEqual(_expectedData.Count, _actualData.Count, string.Format("Collection lengths should be equal")); - + for (var i = 0; i < _actualData.Count; i++) { var expectedItem = _expectedData[i]; @@ -218,14 +216,14 @@ public override bool Equals(object obj) if (ReferenceEquals(null, obj)) return false; if (ReferenceEquals(this, obj)) return true; if (obj.GetType() != this.GetType()) return false; - return Equals((TestItem) obj); + return Equals((TestItem)obj); } public override int GetHashCode() { unchecked { - return (Id*397) ^ (int) Enum; + return (Id * 397) ^ (int)Enum; } } }