简体   繁体   English

如何在执行期间暂停、保存状态并稍后从同一点继续?

[英]How do I pause during execution, save state, and continue from same point later on?

I have a thread that is doing some processing.我有一个线程正在做一些处理。 I would like to be able to stop this thread during execution, somehow save it's position (and the state of the objects it is operating on), and then continue from that that location at a later date (so after my computer has restarted).我希望能够在执行期间停止这个线程,以某种方式保存它的位置(以及它正在操作的对象的状态),然后在以后从那个位置继续(所以在我的计算机重新启动之后)。

In C# this isn't possible right?在 C# 中,这是不可能的,对吗? And if not, what is the proper design to achieve this functionality?如果没有,实现此功能的正确设计是什么?

So my original wish was to have something like所以我最初的愿望是拥有类似的东西

class Foo : Task {   
    void override   Execute(){ 
        //example task
        while(someCondition){
        ...do stuff... 
        }
    }
}

and be able to pause/save at any point within that function.并且能够在该功能内的任何点暂停/保存。 When the function ends, everyone knows it is complete.当功能结束时,每个人都知道它完成了。 As an alternative, perhaps this is the better way to do it作为替代方案,也许这是更好的方法

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();
    }

}

So the first case is a lot simpler for other people who need to inherit my base class as they only have to implement the Execute function.所以对于需要继承我的基类的其他人来说,第一种情况要简单得多,因为他们只需要实现 Execute 函数。 However, in the second case, they have to consider the previous state and also manage where good pause points exist.然而,在第二种情况下,他们必须考虑之前的状态并管理存在良好暂停点的位置。 Is there a better way to do this?有一个更好的方法吗?

What you want could be accomplished by a serializable state machine.你想要的可以通过一个可序列化的状态机来完成。 Basically, you change your local variables into fields in a class and add a field that keeps the state – the position in the code of the original method.基本上,您将局部变量更改为类中的字段,并添加一个保持状态的字段——原始方法在代码中的位置。 This class will be [Serializable] and it will have one method like MoveNext() , which does a piece of work and returns.这个类将是[Serializable]并且它将有一个方法,比如MoveNext() ,它完成一项工作并返回。 When working, you call this method in a loop.工作时,您在循环中调用此方法。 When you want to stop, you wait until the current call finishes, break out of the loop and then serialize the state machine to the disk.当你想停止时,你等到当前调用完成,跳出循环,然后将状态机序列化到磁盘。

Based on the complexity of the original method and how often you do want to “checkpoint” (when the MoveNext() method returns and you can choose to continue or not), the state machine could be as simple as having just one state, or quite complicated.根据原始方法的复杂性以及您希望“检查点”的频率(当MoveNext()方法返回时,您可以选择继续或不继续),状态机可以像只有一个状态一样简单,或者相当复杂。

The C# compiler does very similar transformation when it's compiling iterator blocks (and C# 5's async methods). C# 编译器在编译迭代器块(和 C# 5 的async方法)时执行非常相似的转换。 But it's not meant for this purpose and it doesn't mark the generated class [Serializable] , so I don't think you could use it.但它不是为了这个目的,它没有标记生成的类[Serializable] ,所以我认为你不能使用它。 Although reading some articles about how this transformation is actually done might help you do the same yourself.尽管阅读一些有关如何实际完成此转换的文章可能会帮助您自己做同样的事情。

I cannot answer for C# , but in general this question is calledPersistence and there is no general easy way to solve it (unless the language and operating system provides it).我无法回答C# ,但通常这个问题称为Persistence并且没有通用的简单方法来解决它(除非语言和操作系统提供它)。 You cannot reason in terms of one thread, because the thread you are considering is referencing some other (global or heap) data.您不能就一个线程进行推理,因为您正在考虑的线程正在引用其他一些(全局或堆)数据。 That question is also related to garbage collection (because both garbage collectors and persistence mechanism tend to scan the entire live heap) and databases (notably NoSQL ones).这个问题也与垃圾收集(因为垃圾收集器和持久性机制都倾向于扫描整个活动堆)和数据库(特别是NoSQL的)有关。 So read the GC handbook and textbooks on operating systems , see also websites such as OSDEV .因此,请阅读有关操作系统GC 手册和教科书,另请参阅OSDEV等网站。

See also this draft report, read Queinnec's Lisp in Small Pieces book, and study the source code of existing persistent software, including RefPerSys (and of course Mono , an open source implementation for C#)另请参阅这份报告草稿,阅读 Queinnec 的Lisp in Small Pieces一书,并研究现有持久性软件的源代码,包括RefPerSys (当然还有Mono ,C# 的开源实现)

Things become even more challenging when you want to persist a network (or graph) of processes in the context of cloud computing .当您想要在云计算环境中保留进程网络(或图)时,事情变得更具挑战性。 Then search the web for agent oriented programming .然后在网络上搜索面向代理的编程

At the conceptual level your question is related to continuation-passing style and to callbacks , a topic on which you'll find many ACM -sponsored conferences (eg PLDI , ISMM )在概念层面上,您的问题与continuation-passing stylecallbacks有关,您会发现许多ACM赞助的会议(例如PLDIISMM )都在该主题上

This can be farily easily achieved using WF...it has all the plumbing to explicitly pause and resume tasks (and it takes care of the persistence for you).这可以使用 WF 轻松实现......它具有显式暂停和恢复任务的所有管道(并且它会为您处理持久性)。 Check out this link.看看这个链接。

Probably not be suitable for what you want, but maybe worth investigation.可能不适合你想要的,但可能值得研究。

You could probably set something like this up with an expression tree or method chain.您可能可以使用表达式树或方法链设置类似的内容。 Set up lambdas or small methods for the smallest "atomic" units of work that cannot be interrupted.为不可中断的最小“原子”工作单元设置 lambda 或小型方法。 Then, chain them together with a "supervisor" that will execute each of these chunks in order, but can be told to stop what it is doing in between instructions, save its position along the chain, return and wait to be resumed.然后,将它们与将按顺序执行这些块中的每一个的“监督者”链接在一起,但可以被告知在指令之间停止它正在执行的操作,保存其沿链的位置,返回并等待恢复。 If you wanted the name of a pattern, you might call it a variation on Visitor.如果您想要模式的名称,您可以将其称为 Visitor 的变体。

You want to serialize the state of your object when the process is paused, and then deserialize it once it restarts.您希望在进程暂停时序列化对象的状态,然后在它重新启动后反序列化它。

A very naive implementation would be to create two static methods on your Task class Serialize/Deserialize which use Linq to read/write the state of your object in XML.一个非常简单的实现是在您的 Task 类 Serialize/Deserialize 上创建两个静态方法,它们使用 Linq 在 XML 中读取/写入对象的状态。 When a task is paused call Serialize which dumps the object as xml to disk, when it's restarted call Deserialize which reads the xml.当任务暂停时调用 Serialize 将对象作为 xml 转储到磁盘,当它重新启动时调用 Deserialize 读取 xml。 There is also the XmlSerializer class which may be more robust.还有可能更健壮的XmlSerializer类。

Regardless this is a complex problem, with a conceptually simple solution.无论如何,这是一个复杂的问题,具有概念上简单的解决方案。

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

相关问题 如何将当前执行状态推送到堆栈中以便以后可以继续执行? - How can I push the current execution state into a stack so that I can continue from it later? 如何保存后端执行 state 并稍后恢复? - How to save backend execution state and resume it later? 如何在CUIT执行期间存储应用程序数据以在以后的其他测试中使用 - How do I Store application data during a CUIT execution to use later in another test 如何取消后台工作人员操作以及如何暂停/继续后台工作人员? - How do i cancel a backgroundworker operation and how to pause/continue a backgroundworker? 如何保留并稍后恢复线程的执行状态? - How can I preserve and later resume a thread's execution state? 在程序执行期间,如何告诉不同的类保存到同一文件夹? - How to tell different classes to save to the same folder during execution of a program? 如何在EditorWindow中暂停/继续计时器? - How can I pause/continue a timer in EditorWindow? 如何暂停和继续TPL任务? - How can I pause and continue a TPL task? 如何更新/保存步进值以备后用? - How Do I Update/Save Stepper Value for Later Use? 执行后/执行期间,如何从ASP NET检索SSIS包日志? (C#) - How do I retrieve SSIS package logging from ASP NET after/during execution? (C#)
 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM