/// <summary> /// Connects the pipe to the server. /// </summary> /// <param name="cancellationToken">A token to cancel the request.</param> /// <exception cref="IOException">Thrown when the connection fails.</exception> public async Task ConnectAsync(CancellationToken cancellationToken = default) { if (this.State != PipeState.NotOpened) { throw new InvalidOperationException("Can only call ConnectAsync once"); } if (this.pipeName != null) { this.logger.Log(() => $"Connecting to named pipe '{this.pipeName}' on machine '{this.serverName}'"); } else { this.logger.Log(() => $"Connecting to named pipe"); } if (this.rawPipeStream == null) { this.CreatePipe(); } await this.rawPipeStream.ConnectAsync(cancellationToken).ConfigureAwait(false); this.logger.Log(() => "Connected."); this.wrappedPipeStream = new PipeStreamWrapper(this.rawPipeStream, this.logger); this.Invoker = new MethodInvoker <TRequesting>(this.wrappedPipeStream, this.messageProcessor); this.messageProcessor.StartProcessing(wrappedPipeStream); }
/// <summary> /// Initializes a new instance of the <see cref="RequestHandler"/> class. /// </summary> /// <param name="pipeStreamWrapper">The underlying pipe stream wrapper.</param> /// <param name="handlerFactoryFunc"></param> public RequestHandler(PipeStreamWrapper pipeStreamWrapper, Func <THandling> handlerFactoryFunc) { this.pipeStreamWrapper = pipeStreamWrapper; this.handlerFactoryFunc = handlerFactoryFunc; this.pipeStreamWrapper.RequestHandler = this; }
/// <summary> /// Initializes a new instance of the <see cref="MethodInvoker" /> class. /// </summary> /// <param name="pipeStreamWrapper">The pipe stream wrapper to use for invocation and response handling.</param> public MethodInvoker(PipeStreamWrapper pipeStreamWrapper, PipeMessageProcessor pipeHost) { this.pipeStreamWrapper = pipeStreamWrapper; this.pipeStreamWrapper.ResponseHandler = this; this.pipeHost = pipeHost; }
/// <summary> /// Waits for a client to connect to the pipe. /// </summary> /// <param name="cancellationToken">A token to cancel the request.</param> /// <exception cref="IOException">Thrown when the connection fails.</exception> public async Task WaitForConnectionAsync(CancellationToken cancellationToken = default) { if (this.rawPipeStream == null) { this.CreatePipe(); } await this.rawPipeStream.WaitForConnectionAsync(cancellationToken).ConfigureAwait(false); this.logger.Log(() => "Connected to client."); var wrappedPipeStream = new PipeStreamWrapper(this.rawPipeStream, this.logger); var requestHandler = new RequestHandler<THandling>(wrappedPipeStream, this.handlerFactoryFunc); this.messageProcessor.StartProcessing(wrappedPipeStream); }
/// <summary> /// Starts the processing loop on the pipe. /// </summary> public async void StartProcessing(PipeStreamWrapper pipeStreamWrapper) { if (this.State != PipeState.NotOpened) { throw new InvalidOperationException("Can only call connect once"); } this.State = PipeState.Connected; try { this.workLoopCancellationTokenSource = new CancellationTokenSource(); // Process messages until canceled. while (true) { this.workLoopCancellationTokenSource.Token.ThrowIfCancellationRequested(); await pipeStreamWrapper.ProcessMessageAsync(this.workLoopCancellationTokenSource.Token).ConfigureAwait(false); } } catch (OperationCanceledException) { // This is a normal dispose. this.State = PipeState.Closed; if (this.pipeCloseCompletionSource != null) { this.pipeCloseCompletionSource.TrySetResult(null); } } catch (Exception exception) { this.State = PipeState.Faulted; this.PipeFault = exception; if (this.pipeCloseCompletionSource != null) { if (!(exception is IOException)) { exception = new IOException("Pipe closed with error", exception); } this.pipeCloseCompletionSource.TrySetException(exception); } } }