/// <summary> /// Attaches a tracer to this connection. Only allowed in state 'Initializing'. To avoid race conditions, /// this method should only be used in conjunction with the parameterless constructor (no auto-connect). /// Call this method *before* calling Connect. /// </summary> /// <param name="tracer">Tracer to attach</param> /// <exception cref="ArgumentNullException"><paramref name="tracer"/> is null</exception> /// <exception cref="InvalidOperationException">Connection is not in state 'Initializing'</exception> public void AttachTracer(IFrameTracer tracer) { if (tracer == null) { throw new ArgumentNullException(nameof(tracer)); } if (State != ConnectionState.Initializing) { throw new InvalidOperationException("Connection is not in state 'Initializing'"); } _attachTracerAction += () => { _pump?.AttachTracer(tracer); }; }
public void Start() { Pump = new FramePump(_stream); foreach (var tracer in _tracers) { Pump.AttachTracer(tracer); } _tracers.Clear(); OutboundEp = new OutboundTcpEndpoint(_server, Pump); InboundEp = _server._rpcEngine.AddEndpoint(OutboundEp); Pump.FrameReceived += InboundEp.Forward; State = ConnectionState.Active; PumpRunner = new Thread(o => { try { Thread.CurrentThread.Name = $"TCP RPC Server Thread {Thread.CurrentThread.ManagedThreadId}"; Pump.Run(); } catch (ThreadInterruptedException) { Logger.LogError($"{Thread.CurrentThread.Name} interrupted at {Environment.StackTrace}"); } finally { OutboundEp.Dismiss(); InboundEp.Dismiss(); Pump.Dispose(); Client.Dispose(); lock (_server._reentrancyBlocker) { --_server.ConnectionCount; _server._connections.Remove(this); State = ConnectionState.Down; _server.OnConnectionChanged?.Invoke(_server, new ConnectionEventArgs(this)); } } }); PumpRunner.Start(); }