【问题标题】:file read write memory leak in asp.net mvc applicationasp.net mvc应用程序中的文件读写内存泄漏
【发布时间】:2015-03-17 12:48:39
【问题描述】:

我从文本文件中读取 json 字符串并将 json 字符串转换为对象并将其添加到列表中。然后我在循环中调用instagram feed API,在获得响应后,我将响应字符串转换为json对象并将其添加到列表中。最后,我将对象列表转换为 json 字符串并将其写入文本文件。

我需要更新两个文本文件中的 json 字符串,所以在完成对 instagram 的所有请求后,我将 json 字符串从一个文本文件复制到另一个文本文件。

我的问题

我每 10 分钟调用一次此 InstagramRecentList 方法,以反映我网站中最近的 instagram 提要。当我检查服务器中的内存使用情况时,这个应用程序池在一个阶段也占用了更多内存,所有托管在 IIS 中的应用程序都因此停止工作。执行上述过程的最佳和有效方法是什么,以便我的应用程序不占用更多内存。

Here 是所选进程的屏幕截图,显示了该应用程序池的内存使用情况,截至目前,我每天都在回收应用程序池。如果我停止回收应用程序池,内存使用量会增加。请帮我。对不起我的英语。

public ActionResult InstagramRecentList()
{
    string filepath = Path.Combine(ConfigurationManager.AppSettings["instgramfilepath"], Constants.w_Instagram_recent_listJsonFile);

    string ClientId = ConfigurationManager.AppSettings["instgramclientid"];
    string HondaId = ConfigurationManager.AppSettings["instgramhondaid"];
    WriteInstagramRecentList(filepath, HondaId, ClientId);
    string wp = Path.Combine(ConfigurationManager.AppSettings["instgramfilepath"], Constants.r_Instagram_recent_listJsonFile);
    string Jsonstring = String.Empty;
    using (StreamReader sr = System.IO.File.OpenText(filepath))
    {
        string s = String.Empty;
        while ((s = sr.ReadLine()) != null)
        {
            Jsonstring = Jsonstring + s;
        }
    }

    TextWriter tw = new StreamWriter(wp);
    tw.WriteLine(Jsonstring);
    tw.Close();
    tw.Dispose();
    return View("UpdateResult");
}

private static void WriteInstagramRecentList(string filepath, string HondaId, string ClientId, string nextpageurl = null)
{
    string feedurl = string.Empty;
    List<object> modeldata = new List<object>();
    if (nextpageurl != null)
    {
        feedurl = nextpageurl;

        string Jsonstring = String.Empty;
        using (StreamReader sr = System.IO.File.OpenText(filepath))
        {
            string s = String.Empty;
            while ((s = sr.ReadLine()) != null)
            {
                Jsonstring = Jsonstring + s;
            }
        }
        if (!string.IsNullOrEmpty(Jsonstring))
        {
            modeldata = JsonConvert.DeserializeObject<List<object>>(Jsonstring);
        }
    }
    else
    {
        feedurl = String.Format("https://api.instagram.com/v1/users/{0}/media/recent/?client_id={1}&count={2}", HondaId, ClientId, 200);
    }

    var request = WebRequest.Create(feedurl);
    request.ContentType = "application/json; charset=utf-8";
    string text;
    var response = (HttpWebResponse)request.GetResponse();
    using (var reader = new StreamReader(response.GetResponseStream()))
    {
        text = reader.ReadToEnd();
        if (!string.IsNullOrEmpty(text))
        {
            dynamic result = System.Web.Helpers.Json.Decode(text);
            if (result.data != null)
            {
                modeldata.AddRange(result.data);
            }
            string json = JsonConvert.SerializeObject(modeldata);
            TextWriter tw = new StreamWriter(filepath);
            tw.WriteLine(json);
            tw.Close();
            tw.Dispose();
            if (result.pagination != null && !string.IsNullOrEmpty(result.pagination.next_url) && modeldata.Count < 205)
            {
                WriteInstagramRecentList(filepath, HondaId, ClientId, result.pagination.next_url);
            }

        }
    }
}

【问题讨论】:

  • WriteInstagramRecentList 不需要递归。将其重构为迭代,这使用更少的内存并且在 C# 中(在大多数情况下)性能更高,因为 CLR 不支持尾调用优化。
  • 对不起,@VMAtm,@JNYRanger,@Владислав Фурдак,感谢您的帮助。根据您的 cmets 实现我的代码后,内存使用量有所减少,但仍然占用了大量内存。但我在 newtonsoft json 中发现的主要问题。我使用过 Newtonsoft.Json.4.5.1。来自 instagram 的响应很大而且很复杂,所以在使用 newtonsoft 进行序列化和反序列化时它占用了更多内存。我在这里查看james.newtonking.com 并发现带有内存使用优化的新版本,所以我将我的包从 4.5.1 升级到 6.0.8,现在我的问题已解决,不再有内存泄漏。谢谢

标签: c# asp.net-mvc-4 memory-leaks instagram


【解决方案1】:

我的第一个建议是 - 尽量避免递归调用
WriteInstagramRecentList 方法。

【讨论】:

    【解决方案2】:

    不要在连接字符串时直接使用string 类。它们在 C# 中是不可变的(就像在许多其他语言中一样)。这意味着您每次都在创建一个新字符串。请改用 StringBuilder 类,并且不要创建每一行的副本 - 请改为检查 EndOfStream 属性:

    StringBuilder jsonString = new StringBuilder;
    using (StreamReader sr = System.IO.File.OpenText(filepath))
    {
        while (!sr.EndOfStream))
        {
            jsonString.AppendLine(sr.ReadLine());
        }
    }
    

    或者干脆使用StreamReader类的ReadToEnd方法:

    String jsonString = String.Empty;
    using (StreamReader sr = System.IO.File.OpenText(filepath))
    {
         jsonString = sr.ReadToEnd();
    }
    

    您也可以结合使用这些方法。使用图形时您应该检查的另一件事 - 您是否根据 Instagram 的响应创建了一些图像?如果是这样,请考虑在使用后处理它们。您也可以在TextWriter 对象上使用using 模式,如下所示:

    using (TextWriter tw = new StreamWriter(wp))
    {
        tw.WriteLine(Jsonstring);
    }
    

    把它们放在一起,你可以这样重写你的方法:

    using (StreamReader sr = System.IO.File.OpenText(filepath))
    using (TextWriter tw = new StreamWriter(wp))
    {
        tw.WriteLine(sr.ReadToEnd());
    }
    

    【讨论】:

      猜你喜欢
      • 2019-01-26
      • 1970-01-01
      • 2011-10-29
      • 1970-01-01
      • 1970-01-01
      • 2013-12-13
      • 2016-03-28
      • 2010-11-27
      • 1970-01-01
      相关资源
      最近更新 更多