简体   繁体   English

尝试读取xml文件时的ASP.Net,“在不存在的网络连接上尝试了操作”

[英]ASP.Net when trying to read xml file, “An operation was attempted on a nonexistent network connection”

string url = "http://www.example.com/feed.xml";
var settings = new XmlReaderSettings();
settings.IgnoreComments = true;
settings.IgnoreProcessingInstructions = true;
settings.IgnoreWhitespace = true;
settings.XmlResolver = null;
settings.DtdProcessing = DtdProcessing.Parse;
settings.CheckCharacters = false;
var request = (HttpWebRequest)WebRequest.Create(url);
request.Timeout = 900000;
request.KeepAlive = true;
request.IfModifiedSince = lastModified;
var response = (HttpWebResponse)request.GetResponse();
Stream stream;
stream = response.GetResponseStream();
stream.ReadTimeout = 600000;
var xmlReader = XmlReader.Create(stream, settings);

while (!xmlReader.EOF)
{
...

When I try this on a large xml file (that is also very slow to download), my azure web app throws a blank page after a couple of minutes. 当我在一个大的xml文件上尝试这个(下载速度也很慢)时,我的azure web应用程序会在几分钟后抛出一个空白页面。

I saw this on Azure's Failed Request Tracing Logs: 我在Azure的失败请求跟踪日志中看到了这个:

ModuleName : DynamicCompressionModule ModuleName :DynamicCompressionModule

Notification : SEND_RESPONSE 通知 :SEND_RESPONSE

HttpStatus : 500 HttpStatus :500

HttpReason : Internal Server Error HttpReason :内部服务器错误

HttpSubStatus : 19 HttpSubStatus :19

ErrorCode : An operation was attempted on a nonexistent network connection. ErrorCode :尝试对不存在的网络连接执行操作。 (0x800704cd) (0x800704cd)

As you can see, I have been "playing around" with the timeout settings. 正如你所看到的,我一直在玩“超时设置”。 Also tried catching all exceptions but it doesn't catch any. 还尝试捕获所有异常,但它没有捕获任何。

Also, this works without problems when debugging the web app locally on my computer. 此外,在我的计算机上本地调试Web应用程序时,这没有问题。 It could be that the internet connection at my office is better than Azure's, resulting on the xml file being read fast without any problems. 可能是我办公室的互联网连接比Azure更好,导致xml文件快速读取而没有任何问题。

Any possible workarounds? 任何可能的解决方法? Edit: I want to keep streaming the XML file (I'm avoiding downloading the whole file because the user has an option to read only the first N entries of the feed). 编辑:我想继续流式传输XML文件(我避免下载整个文件,因为用户可以选择只读取Feed的前N个条目)。 In case the problem described above can't be avoided, I will be happy if someone can help me displaying a meaningful message to the user at least, instead of blank page. 如果无法避免上述问题,我很高兴有人可以帮助我至少向用户显示有意义的消息,而不是空白页。

Try using the WebClient Class to get the xml file. 尝试使用WebClient类获取xml文件。

string xmlAsString;
using (var xmlWebClient = new WebClient())
            {
                xmlWebClient.Encoding = Encoding.UTF8;
                xmlAsString = xmlWebClient.DownloadString(url);
            }

XmlDocument currentXml = new XmlDocument();
currentXml.Load(xmlAsString);

You could just use 你可以使用

string url = "http://www.example.com/feed.xml";
using(var reader = XmlReader.Create(url){

And it should work as url are supported (see here ). 并且它应该在URL支持时工作(见这里 )。 And streaming could then be used through yield return x . 然后可以通过yield return x来使用流式传输。 This is probably your best bet, since you can let the native component handle the streaming the way it wants. 这可能是您最好的选择,因为您可以让本机组件按照自己的方式处理流式传输。 You could even chunk the file via the ReadValueChunk method. 您甚至可以通过ReadValueChunk方法对文件进行分块。

Another consideration, and the one I would guess is the issue, is the size of your Azure instance. 另一个考虑因素,也就是我猜的是问题,就是Azure实例的大小。 Azure instances have a notoriously small amount of memory unless on the highest tier. 除非在最高层,否则Azure实例的内存量非常小。

I also do not see you disposing of you of any of your streams, which can also lead to memory leaks and excessive memory usage. 我也没有看到你处理任何你的流,这也可能导致内存泄漏和内存使用过多。

And considering it works on your machine, and most personal computers are at least as powerful as an A3 instance (one tier below the top), as well as having an IDE to clean up any memory leaks locally, and it seems viable the azure instance could be the issue. 并且考虑到它可以在您的机器上运行,并且大多数个人计算机至少与A3实例(顶层以下一层)一样强大,并且具有用于清理本地任何内存泄漏的IDE,并且看起来可行的天蓝色实例可能是问题。

One potential solution would be to use file streaming. 一种可能的解决方案是使用文件流。 Memory streaming and file streaming are very similar after a certain size. 在一定大小之后,内存流和文件流非常相似。 One uses the file system, while the other uses a sys file (IIRC pagefile.sys), so converting to a file stream would have little impact on performance, with the drawback of having to clean up the file after you are done. 一个使用文件系统,而另一个使用sys文件(IIRC pagefile.sys),因此转换为文件流对性能影响不大,缺点是必须在完成后清理文件。 But when dollars are a consideration, disk streaming is cheaper in the azure world. 但是,当美元成为考虑因素时,磁盘流在天蓝色的世界中会更便宜。

try this 试试这个

    static IEnumerable<XElement> StreamCustomerItem(string uri)
   {
    using (XmlReader reader = XmlReader.Create(uri))
    {
        XElement name = null;
        XElement item = null;

        reader.MoveToContent();

        // Parse the file, save header information when encountered, and yield the
        // Item XElement objects as they are created.

        // loop through Customer elements
        while (reader.Read())
        {
            if (reader.NodeType == XmlNodeType.Element
                && reader.Name == "Customer")
            {
                // move to Name element
                while (reader.Read())
                {
                    if (reader.NodeType == XmlNodeType.Element &&
                        reader.Name == "Name")
                    {
                        name = XElement.ReadFrom(reader) as XElement;
                        break;
                    }
                }

                // loop through Item elements
                while (reader.Read())
                {
                    if (reader.NodeType == XmlNodeType.EndElement)
                        break;
                    if (reader.NodeType == XmlNodeType.Element
                        && reader.Name == "Item")
                    {
                        item = XElement.ReadFrom(reader) as XElement;
                        if (item != null)
                        {
                            XElement tempRoot = new XElement("Root",
                                new XElement(name)
                            );
                            tempRoot.Add(item);
                            yield return item;
                        }
                    }
                }
            }
        }
    }
}

static void Main(string[] args)
{
    XStreamingElement root = new XStreamingElement("Root",
        from el in StreamCustomerItem("Source.xml")
        select new XElement("Item",
            new XElement("Customer", (string)el.Parent.Element("Name")),
            new XElement(el.Element("Key"))
        )
    );
    root.Save("Test.xml");
    Console.WriteLine(File.ReadAllText("Test.xml"));
}

based on below XML 基于以下XML

<?xml version="1.0" encoding="utf-8"?>
<Root>
  <Item>
    <Customer>A. Datum Corporation</Customer>
    <Key>0001</Key>
  </Item>
  <Item>
    <Customer>A. Datum Corporation</Customer>
    <Key>0002</Key>
  </Item>
  <Item>
    <Customer>A. Datum Corporation</Customer>
    <Key>0003</Key>
  </Item>
  <Item>
    <Customer>A. Datum Corporation</Customer>
    <Key>0004</Key>
  </Item>
  <Item>
    <Customer>Fabrikam, Inc.</Customer>
    <Key>0005</Key>
  </Item>
  <Item>
    <Customer>Fabrikam, Inc.</Customer>
    <Key>0006</Key>
  </Item>
  <Item>
    <Customer>Fabrikam, Inc.</Customer>
    <Key>0007</Key>
  </Item>
  <Item>
    <Customer>Fabrikam, Inc.</Customer>
    <Key>0008</Key>
  </Item>
  <Item>
    <Customer>Southridge Video</Customer>
    <Key>0009</Key>
  </Item>
  <Item>
    <Customer>Southridge Video</Customer>
    <Key>0010</Key>
  </Item>
</Root>

Fore More details 更多细节

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM