处理连续TCPClient ReadAsync Networkstream异常的正确方法

本文关键字:方法 异常 Networkstream 连续 TCPClient ReadAsync 处理 | 更新日期: 2023-09-27 18:27:09

我有一个应用程序,它运行一个与多个设备通信的后台线程。这些设备根据我无法控制的外部触发器向我发送数据。我必须等待设备向我发送数据并对其进行操作。如果发生异常,我需要在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);我试着把这个放在文本的检查范围内。我打了故障旗,但后来我在上轰炸了。继续。

有人知道我需要什么来修复这个问题吗?这样我就可以正确地捕捉错误并将其提升到UI?这个代码有各种各样的臭味,但我在学习的过程中不断学习。谢谢你能提供的任何帮助。

处理连续TCPClient ReadAsync Networkstream异常的正确方法

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

就我个人而言,我不会将async/await与ContinueWith混合使用。等待已经为您提供了一种方便的方式来执行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()");
    }
}

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