为什么在Stream.ReadAsync()的回调中使用Console.WriteLine()会阻塞?

9

我有一个回调函数,在其中我尝试写入我在重写的ReadAsync()中读取的数据。

private void StreamCallback(byte[] bytes)
{
    Console.WriteLine("--> " + Encoding.UTF8.GetString(bytes)); // the whole application is blocked here, why?
    if (OnDataReceived != null)
    {
        string data = Encoding.UTF8.GetString(bytes);
        OnDataReceived(data);
    }
}

被覆盖的ReadAsync()如下所示。
public override async Task<int> ReadAsync(byte[] buffer, int offset, int count, System.Threading.CancellationToken cancellationToken)
{
    var read = await _originalStream.ReadAsync(buffer, offset, count, cancellationToken);
    _readCallback(buffer);

     return read;
}

我想要实现的是在XmlReader解析网络流之前监控它。这与我的另一个问题有关 > 同时从同一SslStream读取? <。我该怎么做?
更新:
实际上是Encoding.UTF8.GetString(bytes)阻塞了应用程序。为了让问题更完整,我列出了读取XML流的代码。
using (XmlReader r = XmlReader.Create(sslStream, new XmlReaderSettings() { Async = true }))                
{
    while (await r.ReadAsync())
    {
        switch (r.NodeType)
        {
            case XmlNodeType.XmlDeclaration:
                ...
                break;
            case XmlNodeType.Element:
...

为什么不尝试使用 bytes.ToString() 而不是 Encoding.UTF8.GetString(bytes),或者我错过了一些基础知识吗? - Malachi
3
@Malachi:那我应该怎么处理由ToString()产生的System.Byte[]呢? - Tony Stark
1
@TonyStark:其他线程在做什么?特别是,它们中的一个是否正在等待控制台输入(即Console.ReadKeyConsole.ReadLine)? - Jim Mischel
1
如果是这样,请查看此错误报告:https://connect.microsoft.com/VisualStudio/feedback/details/778650/undocumented-locking-behaviour-in-system-console - Jim Mischel
3
我认为控制台锁也是问题所在。你需要发布线程的堆栈跟踪,完整的跟踪信息可以在“调用堆栈”调试器窗口中看到。并且启用Windows更新可以使控制台锁问题自动消失。 - Hans Passant
显示剩余17条评论
1个回答

1
根据您发布的代码,StreamCallback() 将一直阻塞,直到该流结束。您将一个字节指针传递给 Encoding.UTF8.GetString(bytes); 因此,它需要不断查询字节,直到达到结尾。它永远不会到达结尾,因为字节来自流,直到该流关闭。
您需要按特定数量的字节或直到看到某个字符来处理流。

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接