【问题标题】:Proper way to handle a continuous TCPClient ReadAsync Networkstream exception处理连续 TCPClient ReadAsync Networkstream 异常的正确方法
【发布时间】:2014-10-20 08:25:51
【问题描述】:

我有一个运行与多个设备通信的后台线程的应用程序。这些设备根据我无法控制的外部触发器向我发送数据。我必须等待设备向我发送数据并对其进行操作。如果发生异常,我需要在 UI 上显示。

我正在尝试通过网络流连续读取数据。当数据到来时,我需要将它作为一个事件引发,然后再次开始阅读。如果抛出异常(例如设备断开连接),我需要能够处理。

在基地我有一个异步读取的网络流

    public Task<string> ReadLinesAsync(CancellationToken token)
    {
        _readBuffer = new byte[c_readBufferSize];
        // start asynchronously reading data
        Task<int> streamTask = _networkstream.ReadAsync(_readBuffer, 0, c_readBufferSize, token);
        // wait for data to arrive
        Task<String> resultTask = streamTask.ContinueWith<String>(antecedent =>
        {
            // resize the result to the size of the data that was returned
            Array.Resize(ref _readBuffer, streamTask.Result);
            // convert returned data to string
            var result = Encoding.ASCII.GetString(_readBuffer);
            return result; // return read string
        }, token);
        return resultTask;
    }

所以我尝试这样做的方式是在启动时,我通过运行 Start() 方法启动一个正在读取的线程。但是,当抛出异常时,它会杀死我的程序,即使我在它周围设置了一些错误陷阱。我一直试图将它捕获在不同的地方,只是为了看看会发生什么,但我无法找出正确的方法来做到这一点,这样我就可以在不炸毁我的应用程序的情况下向 UI 提出错误。

async public override void Start()
    {
        try
        {
            await _client.ReadLinesAsync(_cts.Token).ContinueWith(ReadLinesOnContinuationAction, _cts.Token);
        }
        catch (AggregateException ae)
        {
            ae.Handle((exc) =>
            {
                if (exc is TaskCanceledException)
                {

                    _log.Info(Name + " - Start() - AggregateException"
                        + " - OperationCanceledException Handled.");
                    return true;
                }
                else
                {
                    _log.Error(Name + " - Start() - AggregateException - Unhandled Exception"
                    + exc.Message, ae);
                    return false;
                }
            });
        }
        catch (Exception ex)
        {
            _log.Error(Name + " - Start() - unhandled exception.", ex);
        }
    }
async private void ReadLinesOnContinuationAction(Task<String> text)
    {
        try
        {
            DataHasBeenReceived = true;
            IsConnected = true;
            _readLines.Append(text.Result);
            if (OnLineRead != null) OnLineRead(Name, _readLines.ToString());
            _readLines.Clear();
            await _client.ReadLinesAsync(_cts.Token).ContinueWith(ReadLinesOnContinuationAction, _cts.Token);
        }
        catch (Exception)
        {
            _log.Error(Name + " - ReadLinesOnContinuationAction()");
        }
    }

调试器通常会在以下行停止: _readLines.Append(text.Result); 我尝试将其放在 text.IsFaulted 标志的检查中,但随后我在 .ContinueWith 上轰炸了。

是否有人对我需要解决此问题有什么想法,以便我可以正确捕获错误并将偶数提升到 UI?这段代码有各种难闻的气味,但我正在学习这一点。感谢您提供的任何帮助。

【问题讨论】:

    标签: c# exception-handling async-await tcpclient networkstream


    【解决方案1】:

    用哪个 ContinueWith 轰炸了?我看到你至少有两个。

    就我个人而言,我不会将 async/await 与 ContinueWith 混合使用。 await 已经为您提供了一种方便的方式来执行 ContinueWith,所以只需使用它。例如:

    public async Task<string> ReadLinesAsync(CancellationToken token)
    {
        _readBuffer = new byte[c_readBufferSize];
        // start asynchronously reading data
        int readResult = await _networkstream.ReadAsync(_readBuffer, 0, c_readBufferSize, token);
        // after data arrives...
    
        // resize the result to the size of the data that was returned
        Array.Resize(ref _readBuffer, streamTask.Result);
        // convert returned data to string
        return Encoding.ASCII.GetString(_readBuffer);
    }
    
    async public override void Start()
    {
        try
        {
            string text = await _client.ReadLinesAsync(_cts.Token);
            await ReadLinesOnContinuationAction(text);
        }
        catch (AggregateException ae)
        {
            ae.Handle((exc) =>
            {
                if (exc is TaskCanceledException)
                {
    
                    _log.Info(Name + " - Start() - AggregateException"
                        + " - OperationCanceledException Handled.");
                    return true;
                }
                else
                {
                    _log.Error(Name + " - Start() - AggregateException - Unhandled Exception"
                    + exc.Message, ae);
                    return false;
                }
            });
        }
        catch (Exception ex)
        {
            _log.Error(Name + " - Start() - unhandled exception.", ex);
        }
    }
    
    async private Task ReadLinesOnContinuationAction(Task<String> text)
    {
        try
        {
            DataHasBeenReceived = true;
            IsConnected = true;
            _readLines.Append(text.Result);
            if (OnLineRead != null) OnLineRead(Name, _readLines.ToString());
            _readLines.Clear();
            string text = await _client.ReadLinesAsync(_cts.Token);
            await ReadLinesOnContinuationAction(text);
        }
        catch (Exception)
        {
            _log.Error(Name + " - ReadLinesOnContinuationAction()");
        }
    }
    

    或者类似的东西。上面显然没有编译,可能需要一点点按摩才能正确。但希望总体思路足够清晰。

    【讨论】:

    • 它在 ReadLinesOnContinuationAction 上继续。谢谢回复。我什至没有想到这一点。今天早上我会试一试,然后告诉你。
    猜你喜欢
    • 2014-02-26
    • 2015-04-24
    • 2011-08-25
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2018-11-07
    相关资源
    最近更新 更多