通过控制台使用文件流写入字节输出进度时出现内存不足异常

2023-12-25

我有以下代码,在写入大文件时抛出内存不足异常。我有什么遗漏的吗?

我不确定为什么它会抛出内存不足错误,因为我认为文件流最多只能使用 4096 字节作为缓冲区?老实说,我不完全确定缓冲区意味着什么,任何建议将不胜感激。

 public static async Task CreateRandomFile(string pathway, int size, IProgress<int> prog)
    {
        byte[] fileSize = new byte[size];
        new Random().NextBytes(fileSize);
        await Task.Run(() =>
           {
               using (FileStream fs = File.Create(pathway,4096))
               {

                   for (int i = 0; i < size; i++)
                   {
                       fs.WriteByte(fileSize[i]);
                       prog.Report(i);
                   }

               }

           }
       );
    }

    public static void p_ProgressChanged(object sender, int e)
    {
        int pos = Console.CursorTop;
        Console.WriteLine("Progress Copied: " + e);
        Console.SetCursorPosition (0, pos);
    }

    public static void Main()
    {
        Console.WriteLine("Testing CopyLearning");
        //CopyFile()
        Progress<int> p = new Progress<int>();
        p.ProgressChanged += p_ProgressChanged;
        Task ta = CreateRandomFile(@"D:\Programming\Testing\RandomFile.asd", 99999999, p);
        ta.Wait();
    }

编辑:99,999,999 只是为了制作 99MB 文件而创建的

注意:我已经注释掉了 prog.Report(i) ,它会正常工作。 似乎由于某种原因,该错误发生在该行

Console.writeline("Progress Copied: " + e);

我不完全确定为什么这会导致错误?那么错误可能是由于 ProgressEvent 引起的?

编辑 2:我遵循建议更改代码,以便使用以下内容每 4000 字节报告进度:

 if (i%4000==0)
     prog.Report(i);

因为某些原因。我现在能够写入高达 900MB 的文件。

我想问题是,为什么“Edit 2”的代码允许它写入 900MB 就可以了?是因为它报告进度并写入控制台的速度比以前少了 4000 倍吗?我没有意识到控制台会占用这么多内存,特别是因为我假设它所做的只是输出“进度已复制”?

Edit 3:

由于某种原因,当我将以下行更改如下时:

 for (int i = 0; i < size; i++)
      {
          fs.WriteByte(fileSize[i]);
          Console.Writeline(i)
          prog.Report(i);
      }

在 prog.Report(i) 之前有一个“Console.Writeline()”,它可以正常工作并复制文件,尽管需要很长时间才能完成。这让我相信这是由于某种原因与控制台相关的问题,但我不确定是什么。


           fs.WriteByte(fileSize[i]);
           prog.Report(i);

您创建了一个消防水带问题。在死锁和线程竞争之后,可能是线程引起的第三个最可能的问题。并且同样难以诊断。

最简单的方法是使用调试器的“调试”+“Windows”+“线程”窗口并查看正在执行 CreateRandomFile() 的线程。运气好的话,你会发现它是完全的并已写入全部 99MB 字节。但控制台上报告的进度是far在此之后,只报告了 125KB 字节写入,给予或采取。

核心问题是 Progress.Report() 的工作方式。它使用 SynchronizationContext.Post() 调用 ProgressChanged 事件处理程序。在控制台模式应用程序中,将调用 ThreadPool.QueueUserWorkItem()。这相当快,您的 CreateRandomFile() 方法不会因此陷入太多困境。

但事件处理程序本身要慢得多,控制台输出也不是很快。因此,实际上,您正在添加线程池工作请求enormous几秒钟之内就发送了 9900 万条信息。线程池调度程序无法跟上,大约有 4 个线程同时执行。所有这些都竞争写入控制台,只有其中之一可以获得底层锁。

所以是线程池调度程序导致了OOM,被迫存储如此多的工作请求。

当然,当您调用 Report() 的频率较低时,消防水带问题就会减轻很多。确保它实际上并不那么简单never会导致问题,尽管直接调用 Console.Write() 是一个明显的修复方法。最终很简单,创建一个对人类有用的用户界面。没有人喜欢疯狂滚动的窗口或模糊的文本。报告进度的频率不超过每秒 20 次对于用户的眼睛来说已经足够好了,控制台可以轻松跟上。

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

通过控制台使用文件流写入字节输出进度时出现内存不足异常 的相关文章

随机推荐

  • extern C 的未定义引用

    我正在尝试使用 Netbeans g 编译一个程序 其中包括 Aquila 一个开源库 https github com zsiciarz aquila 我跟着安装说明 http aquila dsp org download 但是当尝试编
  • 使用默认参数取消引用函数 - C++14 与 C++11

    以下代码无法使用带有选项的 g 版本 5 4 0 进行编译 std c 1y void f int 0 int main f ok f 2 ok f ok c 11 error with c 14 too few arguments to
  • 有没有办法在iPad上查看localStorage的内容?

    在 设置 Safari 中 有一个 数据库 条目 可让我查看在 iPad 上创建的数据库 不是它们的内容 而是它们的大小和来源 但是 我看不到任何方法来查看 localStorage 中的内容 我正在使用控制台访问 Safari 中的 lo
  • keras图像预处理不平衡数据

    All 我正在尝试使用 Keras 对两个类进行图像分类 对于一个类 我的图像数量非常有限 比如 500 至于另一类 我的图像数量几乎是无限的 那么如果我想使用keras图像预处理 该怎么做呢 理想情况下 我需要这样的东西 对于第一类 我提
  • 为什么我的颜色条中有线条?

    Edit 由于这似乎是一个受欢迎的帖子 因此这里的解决方案似乎对我来说效果很好 谢谢 gazzar 和 mfra cbar solids set rasterized True cbar solids set edgecolor face
  • 在 ~/.gitconfig 中放入什么来暗示 --show-signature 对于每个支持它的 git 子命令?

    我刚刚搜索过git config 1 https git scm com docs git config git log 1 https git scm com docs git log and git show 1 https git s
  • 具有多态模型的嵌套形式

    我正在制作一个具有以下属性的应用程序 并且正在创建一个单一表单 以便能够保存目标 目标的任务 目标的里程碑和里程碑的任务 app models goal rb has many tasks as gt achievement has man
  • 如何防止 coclass 实现在 ATL 类型库中公开

    我正在构建一个带有类工厂类型的 ATL 类型库 有点像这样 object uuid interface INumber IDispatch propget id 0 HRESULT Value out retval LONG pVal ob
  • 正则表达式仅匹配一个句子

    PHP中有没有一种正则表达式可以只匹配一个句子 例如以大写字母开头并以大写字母结尾的句子 or preg match regex here g string matches 有时会使用缩写 因此如果后面跟有 2 个字符或更少的单词 则不得结
  • Python Django getattr():属性名称必须是字符串

    我正在使用 python Django 并收到以下错误 getattr attribute name must be string location val getattr obj field if field in headers if
  • 如何阻止 FullRowSelect 同时选择列标题

    我查看了有关 DataGridView SelectionMode 的其他帖子 但没有发现任何人有同样的问题 仅发生在 NET 4 7 2 当我选择一行时 我单击的列的标题也会被选中 如下所示 将以下两行代码添加到您的构造函数中 第一行也可
  • Vuejs 点击复选框事件?

    我在复选框上有一个 v 模型 其值是从循环分配的 我希望单击事件调用一个函数 我需要在其中访问已选中的数据 当单击被触发时 如果我记录状态 它不会打印复选框的当前单击数据 它打印先前单击的复选框数据 是否必须在函数中传递事件并访问数据 di
  • 如何使用adb命令打开和关闭屏幕? [复制]

    这个问题在这里已经有答案了 我正在使用 KEYCODE POWER 来打开和关闭已 root 的手机 以下命令用于打开和关闭屏幕两种情况 adb shell input keyevent KEYCODE POWER 但是 我想在不同的情况下
  • 当默认电子邮件被覆盖时,Djoser 不发送电子邮件

    我有一个使用 Djoser 进行身份验证的 DRF 项目 该计划是覆盖 Djoser 的默认激活电子邮件并发送 HTML 模板电子邮件 这是我所拥有的 settings py DJOSER SEND ACTIVATION EMAIL Tru
  • Jquery无法从每个函数中获取值

    我正在使用其中带有输入字段的表格 我试图从具有相同类的输入字段集中获取值 并与具有不同类名的每个相邻输入进行比较 我可以看到输入中的值 但 jquery 返回的值是空的 subtotal each function var price th
  • .NET 抽象类

    我正在设计一个网站导航层次结构 它是一棵节点树 大多数节点是页面 有些节点是链接 想想 Windows 中的快捷方式 大多数页面都包含 HTML 内容 一些执行代码 我想将它们表示为类和抽象 MustInherit 类的集合 这是我将存储所
  • JavaScript 中的业务逻辑。胖客户端与瘦客户端

    用 JavaScript 在客户端实现业务逻辑是个好主意吗 应该有什么样的逻辑 验证逻辑 与 GUI 有关吗 如果相同的逻辑想要在另一个应用程序 公开的 中使用 并用 JavaScript 实现它 那么您会做什么 这意味着您无法重用该逻辑
  • Google 日历推送通知:未经授权的 webhook 调用

    目前我们正在开发一款处理谷歌日历的 iPhone 应用程序 需要将日历事件同步到服务器端 一切正常 但对于推送通知 我们正在关注这个流程 https developers google com google apps calendar v3
  • 在Python中,什么时候应该使用函数而不是方法?

    Python 的禅宗指出 做事情应该只有一种方法 但我经常遇到决定何时使用函数和何时使用方法的问题 让我们举一个简单的例子 ChessBoard 对象 假设我们需要某种方法来获得棋盘上所有合法的国王走法 我们写 ChessBoard get
  • 通过控制台使用文件流写入字节输出进度时出现内存不足异常

    我有以下代码 在写入大文件时抛出内存不足异常 我有什么遗漏的吗 我不确定为什么它会抛出内存不足错误 因为我认为文件流最多只能使用 4096 字节作为缓冲区 老实说 我不完全确定缓冲区意味着什么 任何建议将不胜感激 public static