0

我有一个页面。在该页面中,一些数据基于服务调用显示。

此服务呼叫可能需要一分钟以上。

因此,我的 Index 操作方法已经做到了不要调用这个长时间的服务调用。

但是这个服务调用是通过页面加载时的 Ajax 调用来调用的。

这个模型正在工作

我想对此进行修改。

我想使用Task.Factory.StartNew索引操作本身在不同的线程中调用此服务调用。即使返回视图,也让该线程在后台工作。而一个单独的 Ajax 调用我应该能够得到服务线程的结果。

这里的挑战是如何在 Ajax 操作方法中访问在 Index 操作方法中启动的踏步的结果?

4

1 回答 1

2

您可以让 Index 操作(启动任务的操作)生成将与此任务关联的唯一编号(可能是 guid),并将条目存储到与此编号关联的缓存中。然后将数字返回到视图。

然后,该任务将在后台静默运行,并可以更新您存储到缓存中的条目(使用诸如任务进度之类的信息,或者如果您无法执行此操作,只需表明任务是否已完成)。任务完成后,从缓存中删除该条目。

视图本身可以定期向另一个控制器操作发送 AJAX 请求并传递任务的 ID。该操作将使用此键在缓存中查找相应的条目,并返回有关正在运行的任务的视图信息。然后视图本身可以更新 UI。

让我们举个例子,好吗?

public ActionResult Index()
{
    var taskId = Guid.NewGuid().ToString();
    var policy = new CacheItemPolicy
    {
        Priority = CacheItemPriority.NotRemovable,
        // Adjust the value to some maximum amount of time that your task might run
        AbsoluteExpiration = DateTime.Now.AddHours(1)
    };
    MemoryCache.Default.Set(taskId, "running", policy);

    Task.Factory.StartNew(key => 
    {
        // simulate a long running task
        Thread.Sleep(10000);

        // the task has finished executing => we could now remove the entry from the cache.
        MemoryCache.Default.Remove((string)key);
    }, taskId);

    return View((object)taskId);
}

然后您可以拥有另一个控制器操作,该操作将由视图通过 AJAX 调用调用以通知任务的进展:

[HttpPost]
public ActionResult TaskProgress(Guid taskId)
{
    var isTaskRunning = MemoryCache.Default.Contains(taskId.ToString());
    return Json(new { status = isTaskRunning });
}

最后你可以有索引视图:

@model string

<div id="status">Task with id @Model has been started and running</div>

<script type="text/javascript">
    // start continuous polling at 1s intervals
    window.setInterval(function() {
        $.ajax({
            url: '@Url.Action("TaskProgress", new { taskId = Model })',
            type: 'GET',
            cache: false,
            success: function(result) {
                if (!result.status) {
                    // the task has finished executing => let's notify the user
                    $('#status').html('The task has finished executing');
                }
            }
        });
    }, 1000);
</script>

当然,这只是一个过于简单的例子。在现实世界的场景中,您将拥有视图模型,对缓存使用复杂的模型,而不仅仅是一个简单的字符串,如果该任务在完成后需要产生一些结果,您可以在其中保存有关任务和任务结果的信息执行,...

于 2013-03-14T07:23:20.227 回答