![](/img/trans.png)
[英]How can I push the current execution state into a stack so that I can continue from it later?
[英]How do I pause during execution, save state, and continue from same point later on?
我有一个线程正在做一些处理。 我希望能够在执行期间停止这个线程,以某种方式保存它的位置(以及它正在操作的对象的状态),然后在以后从那个位置继续(所以在我的计算机重新启动之后)。
在 C# 中,这是不可能的,对吗? 如果没有,实现此功能的正确设计是什么?
所以我最初的愿望是拥有类似的东西
class Foo : Task {
void override Execute(){
//example task
while(someCondition){
...do stuff...
}
}
}
并且能够在该功能内的任何点暂停/保存。 当功能结束时,每个人都知道它完成了。 作为替代方案,也许这是更好的方法
class Foo : Task {
void override Execute(State previousState){
//set someCondition, other stuff
//IsPaused = false;
previousState.setUpStuff();
//example task
while(someCondition){
...do stuff...
if(base.IsPauseRequested){
base.UpdateState(); //this would be a bit different but just to get the idea
base.IsPaused = true;
return;
}
}
base.RaiseNotifyTaskComplete();
}
}
所以对于需要继承我的基类的其他人来说,第一种情况要简单得多,因为他们只需要实现 Execute 函数。 然而,在第二种情况下,他们必须考虑之前的状态并管理存在良好暂停点的位置。 有一个更好的方法吗?
你想要的可以通过一个可序列化的状态机来完成。 基本上,您将局部变量更改为类中的字段,并添加一个保持状态的字段——原始方法在代码中的位置。 这个类将是[Serializable]
并且它将有一个方法,比如MoveNext()
,它完成一项工作并返回。 工作时,您在循环中调用此方法。 当你想停止时,你等到当前调用完成,跳出循环,然后将状态机序列化到磁盘。
根据原始方法的复杂性以及您希望“检查点”的频率(当MoveNext()
方法返回时,您可以选择继续或不继续),状态机可以像只有一个状态一样简单,或者相当复杂。
C# 编译器在编译迭代器块(和 C# 5 的async
方法)时执行非常相似的转换。 但它不是为了这个目的,它没有标记生成的类[Serializable]
,所以我认为你不能使用它。 尽管阅读一些有关如何实际完成此转换的文章可能会帮助您自己做同样的事情。
我无法回答C#
,但通常这个问题称为Persistence并且没有通用的简单方法来解决它(除非语言和操作系统提供它)。 您不能就一个线程进行推理,因为您正在考虑的线程正在引用其他一些(全局或堆)数据。 这个问题也与垃圾收集(因为垃圾收集器和持久性机制都倾向于扫描整个活动堆)和数据库(特别是NoSQL的)有关。 因此,请阅读有关操作系统的GC 手册和教科书,另请参阅OSDEV等网站。
另请参阅这份报告草稿,阅读 Queinnec 的Lisp in Small Pieces一书,并研究现有持久性软件的源代码,包括RefPerSys (当然还有Mono ,C# 的开源实现)
当您想要在云计算环境中保留进程网络(或图)时,事情变得更具挑战性。 然后在网络上搜索面向代理的编程。
在概念层面上,您的问题与continuation-passing style和callbacks有关,您会发现许多ACM赞助的会议(例如PLDI 、 ISMM )都在该主题上
这可以使用 WF 轻松实现......它具有显式暂停和恢复任务的所有管道(并且它会为您处理持久性)。 看看这个链接。
可能不适合你想要的,但可能值得研究。
您可能可以使用表达式树或方法链设置类似的内容。 为不可中断的最小“原子”工作单元设置 lambda 或小型方法。 然后,将它们与将按顺序执行这些块中的每一个的“监督者”链接在一起,但可以被告知在指令之间停止它正在执行的操作,保存其沿链的位置,返回并等待恢复。 如果您想要模式的名称,您可以将其称为 Visitor 的变体。
您希望在进程暂停时序列化对象的状态,然后在它重新启动后反序列化它。
一个非常简单的实现是在您的 Task 类 Serialize/Deserialize 上创建两个静态方法,它们使用 Linq 在 XML 中读取/写入对象的状态。 当任务暂停时调用 Serialize 将对象作为 xml 转储到磁盘,当它重新启动时调用 Deserialize 读取 xml。 还有可能更健壮的XmlSerializer类。
无论如何,这是一个复杂的问题,具有概念上简单的解决方案。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.