Exemplo n.º 1
0
        private async Task ReceiveLoopAsync(CancellationToken cancellationToken)
        {
#pragma warning disable IDE0068 // Use recommended dispose pattern
            var refToThis = ServiceRef.Create <IConnection>(this);
#pragma warning restore IDE0068 // Use recommended dispose pattern
            try
            {
                //if (_receiveLoopCancellationTokenSource != null)
                //{
                //    _receiveLoopCancellationTokenSource.Dispose();
                //    _receiveLoopCancellationTokenSource = null;
                //}

                //_receiveLoopCancellationTokenSource = new CancellationTokenSource();
                _receiveLoopTaskIsRunningEvent.Set();

                //var cancellationToken = _receiveLoopCancellationTokenSource.Token;
                while (true)
                {
                    cancellationToken.ThrowIfCancellationRequested();

                    int messageLength = -1;
                    if (_messageFramingEnabled)
                    {
                        await _receivingStream.ReadBufferedAsync(_messageSizeBuffer, cancellationToken).ConfigureAwait(false);

                        messageLength = BitConverter.ToInt32(_messageSizeBuffer, 0);
                        if (messageLength == 0)
                        {
                            continue;
                        }

                        cancellationToken.ThrowIfCancellationRequested();
                    }

                    if (messageLength == -1)
                    {
                        if (_receivedActionStreamAsync != null)
                        {
                            //await ServiceRef.CallAndWaitAsync(this, () =>
                            //    _receivedActionStreamAsync(refToThis, _receivingStream, cancellationToken)).ConfigureAwait(false);
                            await _receivedActionStreamAsync(refToThis, _receivingStream, cancellationToken);
                        }
                        else
                        {
                            throw new InvalidOperationException("ReceiveActionStreamAsync must be specified to handle variable length messages");
                        }
                    }
                    else
                    {
                        if (_receivedActionStreamAsync != null)
                        {
#pragma warning disable IDE0067 // Dispose objects before losing scope
                            var bufferedStream = new NetworkBufferedReadStream(_receivingStream, messageLength);
#pragma warning restore IDE0067 // Dispose objects before losing scope
                            await ServiceRef.CallAndWaitAsync(this, async() =>
                                                              await _receivedActionStreamAsync(refToThis, bufferedStream, cancellationToken).ConfigureAwait(false)).ConfigureAwait(false);

                            await bufferedStream.FlushAsync().ConfigureAwait(false);
                        }
                        else
                        {
                            var messageBuffer = new byte[messageLength];

                            await _receivingStream.ReadBufferedAsync(messageBuffer, cancellationToken).ConfigureAwait(false);

                            if (_receivedActionAsync != null)
                            {
                                await ServiceRef.CallAndWaitAsync(this, async() =>
                                                                  await _receivedActionAsync(refToThis, messageBuffer, cancellationToken).ConfigureAwait(false)).ConfigureAwait(false);
                            }
                            else //if (_receivedAction != null)
                            {
                                ServiceRef.CallAndWait(this, () => _receivedAction(refToThis, messageBuffer));
                            }
                        }
                    }
                }
            }
            catch (OperationCanceledException)
            {
                System.Diagnostics.Debug.WriteLine($"{GetType()} ReceiveLoopAsync Cancelled");
            }
#if DEBUG
            catch (Exception ex)
            {
                System.Diagnostics.Debug.WriteLine($"{GetType()}{Environment.NewLine}{ex}");
#else
            catch (Exception)
            {
#endif
                //_receiveLoopCancellationTokenSource = null;

                ServiceRef.Call(this, () =>
                {
                    if (State == ConnectionState.Connected)
                    {
                        SetState(ConnectionTrigger.LinkError);
                    }
                });
            }
            finally
            {
                //_receiveLoopCancellationTokenSource = null;
            }
        }