とても興味深い質問です!実際には のタスクではないようですAsyncController
。非同期コントローラーは、サーバー側で長時間実行される単一の HTTP クエリ操作用に設計されています。非同期アクションを使用している場合、これは、実行時間の長い操作中に ASP.Net ワーカー スレッドを解放し、操作の実行中に他の要求を処理できるようにするのに役立ちます。しかし、クライアント側の観点からは、この非同期コントローラーであるかどうかは問題ではありません。クライアントの場合、これは単一の HTTP 要求です。
アプリケーションで実行時間の長いクエリ サービスを使用して、これを再設計する必要があります。このようなワークフローを提供できるコントローラーの例を次に示します。
public class LongOperationsController : Controller
{
public ActionResult StartOperation(OperationData data)
{
Guid operationId = Guid.NewGuid(); // unique identifier for your operation
OperationsService.DoStartOperation(operationId, data); // service starts to perform operation using separate thread
return new JsonResult(operationId); // operation id should be sent to client to allow progress monitoring
}
public ActionResult GetOperationStatus(Guid operationId)
{
var status = OperationsService.GetStatus(operationId); // this method returns some object, that describes status of operation (e.g. progress, current task etc.)
return new JsonResult(status); // returning it to client
}
public ActionResult GetOperationResult(Guid operationId)
{
var result = OperationsService.GetOperationResult(operationId); // this should throw exception if operation is not yet completed
return new JsonResult(result);
}
public ActionResult ClearOperation(Guid operationId)
{
OperationsService.ClearOperationResult(operationId); // we should delete operation result if it was handled by client
return true;
}
}
そして、このコントローラーとやり取りできるクライアント側のコードは次のとおりです。
var operationId;
function startOperation(data) {
$.post('/LongOperations/StartOperation', data, function(response) {
operationId = response; // store operationId
startOperationMonitoring(); // start
}, 'json');
}
function startOperationMonitoring() {
// todo : periodically call updateOperationStatus() to check status at server-side
}
function updateOperationStatus() {
// todo : get result of GetOperationStatus action from controller
// todo : if status is 'running', update progress bar with value from server, if 'completed' - stop operation monitoring and call finishOperation()
}
function finishOperation() {
// todo : get result of GetOperationResult action from controller and update UI
// todo : call ClearOperation action from controller to free resources
}
これは非常に基本的な概念であり、省略されている項目がいくつかありますが、主要なアイデアを理解していただければ幸いです。また、このシステムのコンポーネントをどのように設計するかはあなた次第です。例えば:
- OperationsService にシングルトンを使用するかどうか。
- 操作結果を保存する場所と期間 (DB? キャッシュ? セッション?);
- 本当にリソースを手動で解放する必要があるのか、クライアントが操作を監視するために停止したとき (ユーザーがブラウザーを閉じたとき) はどうすればよいのかなど。
幸運!