监视新数据的网络流

时间:2015-02-12 09:37:53

标签: c# stream network-programming

我正在编写一个对某些网络设备的状态信息感兴趣的应用程序。其中一个设备通过Http提供状态信息并使用多部分消息;第一次查询信息时,它会向下发送整个状态,然后每当设备状态发生变化时,只会根据更改向流发送新的多部分消息。

我正在使用C#,并且有兴趣使用HttpClient或等价物来打开流,读取当前流中的所有信息,然后监视此流以获取新信息,以便我可以更新设备的状态信息因此在申请中。

本质上我的代码看起来像这样

using (var handler = new HttpClientHandler { Credentials = new NetworkCredential(username, password) })
{
    using (var client = new HttpClient(handler))
    {
        var task = client.GetStreamAsync(uri);

        task.Wait();

        var stream = task.Result;

        while(true)
        {
            byte[] bytes = ReadBytesFromStream(stream);

            DoSomethingWithBytes(bytes);
        }
}

现实生活中的代码在一个线程中运行,并且在被告知时需要正确终止。

我遇到的问题是当流中没有任何内容时,对stream.ReadByte()的读取调用会阻塞。如果我在流上放置了ReadTimeout,那么当Read调用失败时(即没有准备好新信息时),CanRead属性设置为false,我必须重新启动该过程,但这样做会再次收到所有原始状态信息只有已经改变的元素。

是否可以做一些事情来保持流存活,直到我告诉它终止,同时如果没有可用的信息,能够解除阻塞?我需要这样做的原因是因为应用程序是多线程的,我需要安全地终止此代码,并且读取会阻止应用程序关闭。

2 个答案:

答案 0 :(得分:2)

我没有使用HttpClient,而是使用HttpWebRequest并将KeepAlive设置为true和AllowReadStreamBuffering属性为true。这样可以使流保持活动状态,并允许您在字节可用时读取字节。

通过保留对从GetResponseStream返回的网络流的引用,我们可以在NetworkStream上调用Dispose,它会中断当前正在进行的任何读取,否则只要需要,读取就可以阻塞即直到它收到解决线程生命周期问题的数据。

答案 1 :(得分:0)

处理“I / O操作阻塞我的线程”问题的正确方法是使用异步I / O. .NET网络组件在这里提供了许多选项,但在您的情况下,您似乎正在从流中读取甚至使用(错误地)GetStreamAsync()方法,因此可以清除代码以正确和干净地处理

例如:

async Task ExecuteUriAsync(string username, string password, Uri uri)
{
    using (var handler = new HttpClientHandler { Credentials = new NetworkCredential(username, password) })
    {
        using (var client = new HttpClient(handler))
        {
            Stream stream = await client.GetStreamAsync(uri);
            byte[] buffer = new byte[10240];

            while(true)
            {
                int byteCount = await stream.ReadAsync(buffer, 0, buffer.Length);

                if (byteCount == 0)
                {
                    // end-of-stream...must be done with the connection
                    return;
                }
                DoSomethingWithBytes(bytes, byteCount);
            }
        }
    }
}

您的帖子对您​​之前的ReadBytesFromStream()方法做了什么以及DoSomethingWithBytes()做了什么都很模糊,但可能您可以弄清楚如何在上面集成该逻辑。