我编写了一个小型的内部C#程序,它可以在各种文件格式之间进行批量转换,主要依赖于其他API。目前,UI生成BackgroundWorker(而不是线程)来处理转换,然后使用在工作人员完成作业时清空的请求填充队列。队列对象本身非常小(3个字符串告诉工作人员该做什么),并且不会对程序的内存占用做出很大贡献。我的内存管理一直很糟糕(完成后处理图像,并在某些点手动垃圾收集。)尽管如此,程序往往一次使用大约100 MB的内存,并使用大约50%的内存总CPU时间。看起来如果我天真地实现了线程,它会很快耗尽系统内存(除非CLR做了一些我不知道的魔法。)
是否有一种简单/有效的方法来生成线程以防止系统耗尽内存,除了捕获OutOfMemory异常并回滚死亡的线程(看起来非常低效,但没有办法保留状态而不使用过多的存储器)?
答案 0 :(得分:2)
如果使用ThreadPool.QueueUserWorkItem生成转换,您将自动获得正在运行的线程数的限制。 ThreadPool在内部对其进行管理,并在池线程可用时立即处理排队的调用。
答案 1 :(得分:0)
限制队列大小并让发件人等待,如果它已满。但你必须凭经验找到正确的队列大小限制。
答案 2 :(得分:0)
内存不足异常可能很棘手,可能是由内存碎片引起的,实际上内存不足。因此,追踪它们可能很棘手。
来自Sweeden(http://blogs.msdn.com/tess/)的微软产品支持的Tess在跟踪内存方面有很多帖子,其中内存将有助于此过程。
您的应用程序的良好配置文件也可以提供帮助。 JetBrains和AQTime一样好。
答案 3 :(得分:0)
对于图像处理应用程序,使用100MB内存并不是很多。
另外,在.net中,当你得到一个OutOfMemory异常时,整个过程就会消失,你无法从中恢复。
如果你需要更多的内存(或更准确地说,更多的地址空间),系统可以让你在使用它时切换内存或切换到64位。
您可以限制队列大小以确保唯一的“重”内存用户是工作线程,您可以拥有多个工作线程,这将增加您的内存使用量,但也会更快地清空队列,请记住在像这样的CPU密集型操作中,线程数比CPU内核多,效率低。
你谈到“天真实现的线程”,多线程充满了陷阱 - 一个天真的实现效率低下且充满了bug。