简体   繁体   English

撤销/重做框架中的内存管理

[英]Memory management in undo/redo framework

I am in the process of implementing undo/redo functionality for a segment of my software developed in C#.我正在为我用 C# 开发的一部分软件实现撤消/重做功能。 The data on which the undo/redo operation occurs is stored as a list of objects List<MyClass> .发生撤消/重做操作的数据存储为对象List<MyClass> The size of the list can become large (>1k) in certain cases.在某些情况下,列表的大小可能会变大 (>1k)。

I want the user to undo/redo as many times as they possibly can.我希望用户尽可能多地撤消/重做。 But if I simply store all the previous states (as in a Memento Pattern) it might lead to the software using up too much memory, which I do not want.但是如果我只是简单地存储所有以前的状态(如在备忘录模式中),它可能会导致软件使用太多内存,这是我不想要的。

The list of solutions I have come up with are:我提出的解决方案列表是:

  1. Store the states in a file somewhere and only read a few states at a time.将状态存储在某个文件中,一次只读取几个状态。 That way I won't use up a lot of RAM but reading and writing to a file might be time-consuming (probably have to run it on another thread).这样我就不会占用大量内存,但读取和写入文件可能会很耗时(可能必须在另一个线程上运行它)。
  2. Calculate the delta between two consecutive states and store that instead.计算两个连续状态之间的增量并存储它。 For example, UNDO: DEL LIST[5] & REDO: INSERT <object> LIST[5]例如, UNDO: DEL LIST[5] & REDO: INSERT <object> LIST[5]

What are some other efficient ways to implement undo/redo functionality and how do they compare to the solutions above?实现撤消/重做功能的其他一些有效方法是什么,它们与上述解决方案相比如何?

My preferred approach is to use different stacks for different sections of the application, and aggregate them together.我的首选方法是对应用程序的不同部分使用不同的堆栈,并将它们聚合在一起。 I find this to be very efficient.我觉得这非常有效。 I released an open source project implementing this approach - https://www.nuget.org/packages/UndoService/我发布了一个实现这种方法的开源项目 - https://www.nuget.org/packages/UndoService/

I've used this approach in conjunction with your first suggestion.我已经将这种方法与您的第一个建议结合使用。 When a background image is changed in my app, it just stores the Id, and loads it from disk as required.当我的应用程序中的背景图像更改时,它只存储 Id,并根据需要从磁盘加载它。 Other objects use less memory, so their whole state is just stored on a stack in RAM.其他对象使用较少的内存,因此它们的整个状态只是存储在 RAM 中的堆栈中。 The undo service uses delegates to access state and generic stacks so it's pretty simple to mix approaches like this.撤消服务使用委托来访问状态和通用堆栈,因此混合这样的方法非常简单。

I've previously used a common approach based on the same concept as your second suggestion.我以前使用过基于与您的第二个建议相同的概念的通用方法。 This was to use the Command pattern with an Undo() method defined in the Command interface.这是将命令模式与命令接口中定义的 Undo() 方法一起使用。 In terms of resources during execution, this is a very efficient approach because it doesn't need to store state at all, only the commands.就执行期间的资源而言,这是一种非常有效的方法,因为它根本不需要存储状态,只需要存储命令。 However, I dropped it in favour of Memento because of the additional development time and complexity it involved.但是,我放弃了它而支持 Memento,因为它涉及额外的开发时间和复杂性。 That said, it would be a good fit for some projects, especially where the number of commands is not too great or the memory imprint of the application state is significant.也就是说,它非常适合某些项目,尤其是在命令数量不是太多或应用程序状态的内存印记很重要的情况下。

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

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