首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >XmlWriter异步方法

XmlWriter异步方法
EN

Stack Overflow用户
提问于 2013-05-20 08:45:50
回答 3查看 5.2K关注 0票数 12

我在msdn文档http://msdn.microsoft.com/en-us/library/system.xml.xmlwriter.aspx中找到了异步使用XmlWriter的示例。

代码语言:javascript
复制
async Task TestWriter(Stream stream) 
{
    XmlWriterSettings settings = new XmlWriterSettings();
    settings.Async = true;
    using (XmlWriter writer = XmlWriter.Create(stream, settings)) {
        await writer.WriteStartElementAsync("pf", "root", "http://ns");
        await writer.WriteStartElementAsync(null, "sub", null);
        await writer.WriteAttributeStringAsync(null, "att", null, "val");
        await writer.WriteStringAsync("text");
        await writer.WriteEndElementAsync();
        await writer.WriteProcessingInstructionAsync("pName", "pValue");
        await writer.WriteCommentAsync("cValue");
        await writer.WriteCDataAsync("cdata value");
        await writer.WriteEndElementAsync();
        await writer.FlushAsync();
    }
}

我所知道的关于线程和异步编程的所有知识都告诉我,这太慢了,使用同步写方法会快得多。我已经修改了这段代码并对其进行了测试。我发现我是对的,对于超过100Mb的文件,我的同步代码快了3-4倍,在我的环境中,小于10mb的文件,我的同步代码快了8-10倍。

那么我的问题是,有没有这样的代码是可用的,并提供合理的性能收益的场景?

EN

回答 3

Stack Overflow用户

回答已采纳

发布于 2013-05-20 09:47:26

首先,我必须对基准测试提出质疑。对于100MB的文件来说,速度慢3-4倍是非常重要的。

但不管怎样,async并不是为了让事情做得更快。它是关于在操作进行的同时做一些其他的事情。在客户端,您可以获得响应能力的好处;在服务器端,您可以获得可伸缩性的好处。

折衷是操作本身实际上更慢(但它应该稍微慢一点,而不是慢3-4倍)。很可能您并没有使用真正的异步流进行写入(您必须专门异步打开一个文件流才能获得一个异步流)。

票数 11
EN

Stack Overflow用户

发布于 2016-05-23 20:39:30

在实现async/await时,有一些判断要求:即,您正在等待的操作是否可能包含足够的延迟,以至于async/await的小开销是值得的。作为Stephen points out,微软的recommends 50 milliseconds作为一个经验法则的阈值。

在您的示例代码中,您的任何操作都不太可能超过50毫秒。

您的真实CDATA部分可能是async/await的一个有价值的候选。在现实世界中,我们经常将base64编码的PDF写成XML流。在这样的示例中,您可能会发现等待代码的那部分是值得的。

代码语言:javascript
复制
async Task TestWriter(Stream stream, Stream sourceDocument)
{
    XmlWriterSettings settings = new XmlWriterSettings();
    settings.Async = true;
    using (XmlWriter writer = XmlWriter.Create(stream, settings))
    {
        writer.WriteStartElement("pf", "root", "http://ns");
        writer.WriteStartElement(null, "sub", null);
        writer.WriteAttributeString(null, "att", null, "val");
        writer.WriteString("text");
        writer.WriteEndElement();


        // Write the source document
        writer.WriteStartElement(null, "SourceDocument", null);
        Byte[] buffer = new Byte[4096];
        int bytesRead = await sourceDocument.ReadAsync(buffer, 0, 4096);
        while (bytesRead > 0)
        {
            await writer.WriteBase64Async(buffer, 0, bytesRead);
            bytesRead = await sourceDocument.ReadAsync(buffer, 0, 4096);
        }
        writer.WriteEndElement(); // SourceDocument

        writer.WriteEndElement(); // pf
        await writer.FlushAsync();
    }
}

当然,如果你在代码的任何部分咬掉了async/await,你必须在你的整个调用堆栈中实现它,以使它变得有价值,包括像斯蒂芬在他的评论中提到的用async标志打开文件这样的微妙之处。

票数 5
EN

Stack Overflow用户

发布于 2013-05-25 07:11:43

我认为Stephen Cleary的答案是正确的,应该被接受为答案。然而,我只想把我的观点放在这里,因为它可能太大了,无法评论。

在我看来,async/await关键字有两个显著的优势:

1) await是一个非阻塞等待-传统上,当我们启动一个异步任务(比如在另一个线程上)并想要它的结果/完成时,我们使用了Wait(),WaitAll(),Thread.Join()等(我们也使用了APM和EAP -我会在第二点提到它)。这些都是阻塞调用-意味着它们阻塞线程(如Thread.Sleep)。因此,如果UI线程阻塞,UI将冻结--如果太多的ThreadPool线程阻塞,那么ThreadPool不得不承受创建新线程的开销。通过使用async/await -我们能够执行非阻塞等待。在高层,async/await关键字将把方法分解成一个状态机(例如,等待之前和之后的一组委托),并在异步任务结束时调度委托(使用TPL任务调度程序)。这样我们就可以在不冻结UI或阻塞ThreadPool线程的情况下等待。因此,总结async/await将节省资源(线程),并且不会加快速度-它将有自己的状态机和调度开销。

2) async/await将代码的可读性提高了无数倍-如果你使用过EAP或APM (它们在某种程度上是非阻塞的)-那么你必须颠倒你的代码。很难弄清楚谁在调用谁-在哪里处理异常。开发人员的噩梦。使用async/await,我们可以编写看起来像同步的异步代码。

async/await有它自己的方式来思考异步代码,并且有它自己的一组陷阱-所以,你必须小心地使用它。

我认为MSDN上的示例只是为了演示API。

票数 2
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/16641074

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档