/// <inheritdoc /> public async Task StartListeningAsync(CancellationToken cancelToken = default(CancellationToken)) { try { if (!isConnected) { throw new InvalidOperationException($"Cannot start listening with {nameof(StartListeningAsync)} when internal {nameof(SerialPort)} {InternallyManagedPort} is not connected/open."); } while (isConnected && !cancelToken.IsCancellationRequested) { //TODO: Handle cancellation tokens better. TMessageType message = await MessageDeserializer.ReadMessageAsync(InternallyManagedPort, cancelToken) .ConfigureAwait(false); //Don't dispatch if canceled. if (cancelToken.IsCancellationRequested || !isConnected) { return; } //A message was recieved and deserialized as the strategy implemented. //Therefore we should assume we have a valid message and then pass it to the message dispatching strategy. await MessageDispatcher.DispatchMessageAsync(message) .ConfigureAwait(false); } } catch (Exception e) { OnExceptionEncountered?.Invoke(this, e); throw; } finally { Dispose(); //TODO: Should we assume disconnection just because listening stopped? _ConnectionEvents.InvokeClientDisconnected(); } }