简体   繁体   English

如何保存后端执行 state 并稍后恢复?

[英]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.我有一个 .NET 核心应用程序,它通过一些 web API 与 angular 前端进行通信。 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.由于一些无法避免的技术问题,为了实现这个概念,我能想到的唯一可能的解决方案是以某种方式序列化内部 state (包括本地范围变量的 state 在内的所有内容),保存执行点,将此信息存储在某处,然后在用户输入后,最终恢复所有数据并从中断处继续执行。

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。

StartExecution fires and forget Operation. StartExecution 触发并忘记操作。

Operation does its work until it needs to update the UI.操作完成它的工作,直到它需要更新 UI。 So it creates a TaskCompletionSource that will await.所以它创建了一个等待的 TaskCompletionSource。 Its result will be set when the user click Continue It does this with SignalR sending also the generated uid.它的结果将在用户单击 Continue 时设置它通过 SignalR 执行此操作,同时发送生成的 uid。

The UI updates and stores the uid, then wait for the user to press Continue. UI 更新并存储 uid,然后等待用户按 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.当用户按下 Continue 时,如果用户想要继续作业,它会调用 FinishJob 并传递 uid 和 true。

FinishJob set the result of the previously instantiated TaskCompletionSource FinishJob 设置之前实例化的 TaskCompletionSource 的结果

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

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