0

ページがあります。そのページには、サービス呼び出しに基づいていくつかのデータが表示されます。

このサービス コールには 1 分以上かかる場合があります。

したがって、私の Index アクション メソッドは、この長いサービス コールを呼び出さないようにしました。

ただし、このサービス呼び出しは、ページの読み込み時に Ajax 呼び出しを介して呼び出されます。

このモデルは機能しています

これに修正を加えたいと思います。

Task.Factory.StartNewインデックス アクション自体を使用して、別のスレッドでこのサービス コールを呼び出したいと思います。ビューが返されても、そのスレッドをバックグラウンドで動作させます。そして、別の Ajax 呼び出しで、サービス スレッドの結果を取得できるはずです。

ここでの課題は、Ajax アクション メソッドの Index アクション メソッドで開始されたトレッドの結果にどのようにアクセスできるかということです。

4

1 に答える 1

2

インデックス アクション (タスクを開始するアクション) で、このタスクに関連付けられる一意の番号 (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 });
}

最後に、Index ビューを使用できます。

@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 に答える