【问题标题】:out of memory exception on StringWriter using MVC, can memory be increased?使用MVC的StringWriter内存不足异常,可以增加内存吗?
【发布时间】:2013-10-17 15:09:28
【问题描述】:

我必须创建一个大型 XML 电子表格,现在它似乎已经达到了可以一次性处理的阈值。

我不确定如何拆分它,所以想知道是否有办法增加内存分配以供内部使用?

导致错误的代码如下:

private string RenderViewToString()
{
    using (var writer = new StringWriter())
    {
        var view = ViewEngines.Engines.FindView(_context, _viewName, null).View as RazorView;
        var viewDataDictionary = new ViewDataDictionary<TModel>(_model);
        var viewCtx = new ViewContext(_context, view, viewDataDictionary, new TempDataDictionary(), writer);
        viewCtx.View.Render(viewCtx, writer);
        return writer.ToString();
    }
}

当用户决定从可能的数据组合中下载所有数据时,它落在Render() 上,在数据丰富之前,此文件将大约 55mb 转换为 Excel 文档。现在列已经翻了一番,渲染编写器的代码行正在倒塌。

viewCtx.View.Render(viewCtx, writer);

有没有人有解决方法或知道如何将相关数据拆分成可管理的块而不用重新编码?

它从视图模型中获取数据,并且它本身需要跨多个表的 1 到数万行,并且所有这些都是用户在单个 Excel 下载中需要的,这会导致问题。

字符串输出到这段代码:

    protected override void WriteFile(HttpResponseBase response)
    {
        response.Write(RenderViewToString());

    }

但是是否需要返回字符串的整个问题是无关紧要的,因为由于 ViewContext.View.Render(ViewContext, TextWriter) 倒下,它永远不会走那么远,所以有没有办法渲染 ViewContext由于相对较小的文件 (60+ MB) 导致它出现问题而不会翻倒的东西?

我曾尝试允许在 web.config 中使用大文件(一位同事建议这样做),但没有奏效。

目前 ViewContext 太大而无法渲染,所以我只需要找到一种方法来渲染它而不使用内置的,有什么想法吗?

----- 编辑-----

非常感谢 Joe,我修改了您的代码,因为我没有设置 IIS 来使用 HttpContext 标头,但以下代码成功了:

        HttpContext.Current.Response.Clear();
        using (var writer = new StreamWriter(HttpContext.Current.Response.OutputStream))
        {
            var view = ViewEngines.Engines.FindView(_context, _viewName, null).View
                as RazorView;
            var viewDataDictionary = new ViewDataDictionary<TModel>(_model);
            var viewCtx = new ViewContext(_context,
                view, viewDataDictionary, new TempDataDictionary(), writer);
            viewCtx.View.Render(viewCtx, writer);
        }
        return null;

现在生成一个 70MB 的文件没有问题。

【问题讨论】:

  • 是的,安装更多内存 ;)
  • 更多 RAM 无济于事(除非您可以将 1TB 放入 64 位 PC 中:))。这里需要一个分页/拆分数据的策略。
  • 您真的需要字符串本身,还是写入某种输出,例如文件或 HTTP 响应?
  • @Joe - 输出是一个 Excel 文件,允许用户保存或打开它。仅此而已。
  • 结帐stackoverflow.com/questions/1569532/…。它展示了如何返回纯文本文件,但您绝对可以对其进行调整以满足您的需求。

标签: xml asp.net-mvc out-of-memory


【解决方案1】:

您将视图输出写入字符串,然后将其写入响应。您可能想要做的是跳过中间人,并将视图直接写入响应。由于Render 方法接受任何TextWriter,因此您可以将Response.OutputStream 传递给您的StreamWriter,而不仅仅是写入纯字符串。

比如:

System.Web.HttpContext.Current.Response.Clear();
System.Web.HttpContext.Current.Response.Headers["content-disposition"] = 
    "attachment;filename=somefile.txt"; // or whatever
System.Web.HttpContext.Current.Response.Headers["content-type"] =
    "text/plain"; // or whatever
using (var writer = new StreamWriter(System.Web.HttpContext.Current.Response.OutputStream))
{
    var view = ViewEngines.Engines.FindView(_context, _viewName, null).View
        as RazorView;
    var viewDataDictionary = new ViewDataDictionary<Foo>(_model);
    var viewCtx = new ViewContext(_context, 
        view, viewDataDictionary, new TempDataDictionary(), writer);
    viewCtx.View.Render(viewCtx, writer);
}
return null;

【讨论】:

  • 干杯我会看看并报告。
  • 工作一天后又失败了...还有其他想法吗?
  • 不是真的 - 这应该解决你从大字符串中遇到的问题。但是如果你在内存中有一个不同的大项目,比如你的模型或字典,我不知道你是否可以轻松地修复它。解决这类问题通常意味着流数据而不是预先构建所有数据,但我不知道在这种类型的数据下你是否能够做到这一点。我可能会建议您探索将数据拆分成更小的块,这样您一次可以减少内存。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2010-10-05
  • 1970-01-01
相关资源
最近更新 更多