i8a*_*bug 10 c# design-patterns
我有一个正在做一些处理的线程.我希望能够在执行期间停止此线程,以某种方式保存它的位置(以及它正在操作的对象的状态),然后在以后从该位置继续(因此在我的计算机重新启动后).
在C#中,这是不可能的吗?如果没有,实现此功能的正确设计是什么?
所以我最初的愿望是拥有类似的东西
class Foo : Task {
void override Execute(){
//example task
while(someCondition){
...do stuff...
}
}
}
Run Code Online (Sandbox Code Playgroud)
并能够在该功能中的任何点暂停/保存.当功能结束时,每个人都知道它已经完成.作为替代方案,也许这是更好的方法
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();
}
}
Run Code Online (Sandbox Code Playgroud)
因此,对于需要继承我的基类的其他人来说,第一种情况要简单得多,因为他们只需要实现Execute函数.但是,在第二种情况下,他们必须考虑先前的状态,并管理存在良好暂停点的位置.有一个更好的方法吗?
您想要的可以通过可序列化的状态机来完成。基本上,您将局部变量更改为类中的字段,并添加一个保留状态的字段-原始方法的代码中的位置。此类将是[Serializable]并且它将具有一个类似的方法MoveNext(),该方法完成了一部分工作并返回。工作时,您可以循环调用此方法。当您要停止时,您要等到当前调用结束后才退出循环,然后将状态机序列化到磁盘上。
根据原始方法的复杂性以及您想要“检查点”的频率(MoveNext()方法返回时,您可以选择继续还是不选择),状态机可能就像只有一个状态一样简单,或者非常复杂。
C#编译器在编译迭代器块(和C#5的async方法)时会执行非常相似的转换。但这不是为了这个目的,也没有标记生成的类[Serializable],所以我认为您不能使用它。尽管阅读一些有关如何实际完成此转换的文章可能会帮助您自己做同样的事情。