简体   繁体   中英

How to save backend execution state and resume it later?

I have a .NET Core application that communicates with the angular front end through some web APIs. There's one part of the application that needs to wait for some user input before it can continue with its work, something like this:

前端后端交互

Because of some technical problems which cannot be avoided, in order to implement this concept, the only possible solution that I could think of is to somehow serialize the internal state (everything including the state of the locally scoped variables), save the point of execution, store this information somewhere and then, after the user input, finally restore all the data and continue the execution from where it left off.

Is this possible to do? How would you proceed to implement it?

How about this:

private static ConcurrentDictionary<string, TaskCompletionSource<bool>> taskCompletionSources = new ConcurrentDictionary<string, TaskCompletionSource<bool>>();

public IActionResult StartExecution(...)
{
    ...
    Operation(...); // Non-blocking call
    ...
}

private async Task Operation(...)
{
    if(condition) {
        if(condition) {
            //[wait for input]
            var tcs = new TaskCompletionSource<bool>(TaskCreationOptions.LongRunning | TaskCreationOptions.RunContinuationsAsynchronously); // bool or whatever the user response will give us
            var uid = // generate some unique id (like Guid.NewGuid())
            taskCompletionSources.TryAdd(uid, tcs);
            //////////////////////////////////////////////////////////////////// 
            // Now we notify client to update UI with something like SignalR  //
            //////////////////////////////////////////////////////////////////// 
            var userChoice = await tcs.Task; // Wait until user answers (FinishJob will give us the user choice)
            taskCompletionSources.TryRemove(uid, out tcs);
            ...execute some logic...
        }
        ...execute some logic...
    }
    ...execute some logic...
}

public IActionResult FinishJob(string uid, bool yesNo)
{
    if(taskCompletionSources.TryGetValue(uid, out var tcs))
        tcs.SetResult(yesNo); // This will unblock the await in Operation()
}

So basically when the user press Start Button, it performs a call to StartExecution.

StartExecution fires and forget Operation.

Operation does its work until it needs to update the UI. So it creates a TaskCompletionSource that will await. Its result will be set when the user click Continue It does this with SignalR sending also the generated uid.

The UI updates and stores the uid, then wait for the user to press Continue.

When the user press Continue, it performs a call to FinishJob passing the uid and true if the user want to continue the job.

FinishJob set the result of the previously instantiated TaskCompletionSource

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