.NET中的异步XmlReader?

有没有办法异步访问XmlReader? xml从许多不同的客户端(例如XMPP)进入网络; 它是...</action >标记的恒定流。

我所追求的是能够使用类似BeginRead / EndRead的界面。 我设法提出的最佳解决方案是在底层网络流上对0字节进行异步读取,然后当一些数据到达时,在XmlReader上调用Read-但是这将阻塞直到节点中的所有数据变得可用。 该解决方案看起来大致如此

 private Stream syncstream; private NetworkStream ns; private XmlReader reader; //this code runs first public void Init() { syncstream = Stream.Synchronized(ns); reader = XmlReader.Create(syncstream); byte[] x = new byte[1]; syncstream.BeginRead(x, 0, 0, new AsynchronousCallback(ReadCallback), null); } private void ReadCallback(IAsyncResult ar) { syncstream.EndRead(ar); reader.Read(); //this will block for a while, until the entire node is available //do soemthing to the xml node byte[] x = new byte[1]; syncstream.BeginRead(x, 0, 0, new AsynchronousCallback(ReadCallback), null); } 

编辑:如果一个字符串包含一个完整的xml节点,这是一个可能的算法?

 Func nodeChecker = currentBuffer => { //if there is nothing, definetly no tag if (currentBuffer == "") return false; //if we have , hold on, else pass it on if (currentBuffer.Contains("")) return false; if (currentBuffer.Contains("")) return true; //these tag-related things will also catch  processing instructions //if there is a , we still have an open tag if (currentBuffer.Contains("")) return false; //if there is a , we have a complete element. //>... if (currentBuffer.Contains("")) return true; //if there is no , we have a complete text node if (!currentBuffer.Contains("")) return true; //> and no  //by default, don't block return false; }; 

XmlReader以4kB的块缓冲,如果我记得几年前我看过这个时的情况。 您可以将入站数据填充到4kB(ick!),或者使用更好的解析器。 我通过将James Clark的XP(Java)移植到C#作为Jabber-Net的一部分来解决这个问题,这里:

http://code.google.com/p/jabber-net/source/browse/#svn/trunk/xpnet

这是LGPL,只处理UTF8,没有打包使用,几乎没有文档,所以我不建议使用它。 🙂

最简单的方法就是将它放在另一个线程上,也许是一个ThreadPool,具体取决于它保持活动的时间长度。 (不要将线程池线程用于真正长时间运行的任务)。

.NET 4.5中的XmlReader具有涉及IO的大多数方法的异步版本。

在这里查看示例代码。

这非常棘手,因为XmlReader不提供任何异步接口。

当你要求它读取0字节时,我不确定BeginRead异步程度 – 它也可以立即调用回调,然后在调用Read时阻塞。 这可能与直接调用Read然后调度线程池中的下一个Read (例如使用QueueWorkItem

最好在网络流上使用BeginRead来读取数据,例如10kB块(当系统等待数据时,你不会阻塞任何线程)。 当你收到一个块时,你会将它复制到一些本地MemoryStream ,你的XmlReader将从这个MemoryStream读取数据。

这仍然有问题 – 复制10kB数据并多次调用Read ,最后一次调用将阻塞。 然后,您可能需要复制较小的数据块以取消阻止挂起的Read调用。 完成后,您可以再次启动一个新的BeginRead调用,以异步方式读取大部分数据。

老实说,这听起来很复杂,所以如果有人想出更好的答案我会很感兴趣。 但是,它至少为您提供了一些保证的异步操作,这些操作需要一些时间,并且在此期间不会阻塞任何线程(这是异步编程的基本目标)。

旁注:您可以尝试使用F#异步工作流来编写它,因为它们使异步代码变得更加简单。我描述的技术即使在F#中也会很棘手)

看起来DOT NET 4.5在XmlReader上有一个bool Async属性,在3.5中没有。 也许那会对你有用吗?

你在寻找类似XamlReader.LoadAsync方法的东西吗?

异步XAML加载操作最初将返回纯粹是根对象的对象。 异步地,XAML解析然后继续,并且在根下填充任何子对象。