简体   繁体   中英

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? 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. 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. 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.

The C# compiler does very similar transformation when it's compiling iterator blocks (and C# 5's async methods). 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. 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). 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). So read the GC handbook and textbooks on operating systems , see also websites such as 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#)

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 )

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). 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. 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.

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. 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. There is also the XmlSerializer class which may be more robust.

Regardless this is a complex problem, with a conceptually simple solution.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

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