【问题标题】:How to save backend execution state and resume it later?如何保存后端执行状态并稍后恢复?
【发布时间】:2021-08-03 16:07:10
【问题描述】:

我有一个 .NET Core 应用程序,它通过一些 Web API 与 Angular 前端进行通信。 应用程序的一部分需要等待用户输入才能继续工作,如下所示:

由于一些无法避免的技术问题,为了实现这个概念,我能想到的唯一可能的解决方案是以某种方式序列化内部状态(包括本地范围变量的状态在内的所有内容),保存执行点,将此信息存储在某处,然后在用户输入后,最终恢复所有数据并从中断处继续执行。

这可能吗?您将如何着手实施?

【问题讨论】:

  • 您可以使用 BackGroundWorker,然后在工作完成时发生事件。
  • “我能想到的唯一可能的解决方案是以某种方式序列化内部状态和执行点,将其保存在某处并在用户输入后恢复它,从它离开的地方继续。”。确切的问题是什么?因为这个陈述(几乎)证明你知道如何解决这个问题。
  • BTW: "2. 还有其他更适合这个问题的方法吗?"是关闭这个问题的理由,因为它征求意见......
  • @Luuk 这是概念方法,但我不确定这是否真的可以实现。我试着环顾四周,但仍然找不到任何有用的东西。
  • 你的问题非常广泛,很难回答'一般',因为诸如“因为逻辑不能那样分开”和“等待期后只调用另一个方法”之类的陈述会导致一些逻辑缺失。”也许您应该详细说明您的真正问题。

标签: c# .net .net-core backend .net-standard


【解决方案1】:

这个怎么样:

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

所以基本上当用户按下开始按钮时,它会执行对 StartExecution 的调用。

StartExecution 触发并忘记操作。

在需要更新 UI 之前,操作会一直工作。 所以它创建了一个等待的 TaskCompletionSource。当用户单击继续时,将设置其结果 它通过 SignalR 发送生成的 uid 来做到这一点。

UI 更新并存储 uid,然后等待用户按 Continue。

当用户按下 Continue 时,如果用户想要继续作业,它会调用 FinishJob 并传递 uid 和 true。

FinishJob 设置之前实例化的TaskCompletionSource的结果

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2015-12-31
    • 2012-09-17
    • 1970-01-01
    • 1970-01-01
    • 2013-05-16
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多