我有一个正在做一些处理的线程。我希望能够在执行过程中停止这个线程,以某种方式保存它的位置(以及它正在操作的对象的状态),然后在以后的某个日期(所以在我的计算机重新启动之后)从该位置继续。
在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函数。然而,在第二种情况下,他们必须考虑之前的状态,并管理存在良好暂停点的位置。有没有更好的方法来做这件事?
发布于 2011-11-04 00:00:56
您需要的功能可以通过一个可序列化的状态机来实现。基本上,您将局部变量更改为类中的字段,并添加一个字段来保持状态-原始方法代码中的位置。这个类将是[Serializable],它将有一个像MoveNext()这样的方法,该方法完成一部分工作并返回。在工作时,您可以在循环中调用此方法。当您想要停止时,您可以等待当前调用完成,中断循环,然后将状态机序列化到磁盘。
根据原始方法的复杂性和您希望“检查点”的频率(当MoveNext()方法返回时,您可以选择是否继续),状态机可以像只有一个状态一样简单,也可以非常复杂。
C#编译器在编译迭代器块(以及C# 5的async方法)时会进行非常类似的转换。但是它不是为了这个目的,并且它没有标记生成的类[Serializable],所以我不认为你可以使用它。不过,阅读一些关于这种转换是如何实际完成的文章可能会帮助您自己做同样的事情。
发布于 2011-11-03 22:48:14
我不能回答C#,但通常这个问题被称为Persistence,没有通用的简单方法来解决它(除非语言和操作系统提供了它)。您不能根据一个线程进行推理,因为您正在考虑的线程正在引用其他一些(全局或堆)数据。这个问题也与garbage collection (因为垃圾收集器和持久化机制都倾向于扫描整个实时堆)和databases (特别是NoSQL )有关。因此,请在上阅读和教科书,也可参阅OSDEV等网站。
另请参阅this draft报告,阅读Queinnec的一书,并研究现有持久性软件的源代码,包括RefPerSys (当然还有Mono,它是C#的开源实现)
当您想要在cloud computing上下文中持久化processes的网络(或图)时,事情变得更加具有挑战性。然后在网上搜索agent oriented programming。
在概念层面上,您的问题与continuation-passing style和callbacks相关,在这个主题上,您可以找到许多ACM-sponsored会议(例如,PLDI、ISMM)
发布于 2011-11-04 00:09:50
使用WF...it可以很容易地实现这一点,它具有显式暂停和恢复任务的所有功能(并且它会为您处理持久性)。Check out this link.
可能不适合你想要的东西,但也许值得研究一下。
https://stackoverflow.com/questions/7996778
复制相似问题