2010-12-01 27 views
15

ASP.NET MVC 2でdocumentation on AsyncControllersを読んだ後、このシナリオでajaxプログレスバーを実装する最良の方法が何か不思議です。チュートリアルではこれをまったくカバーしていないのは少し奇妙なようです。ASP.NET MVCで実装された長期実行タスクの進行状況バーを実装する2 AsyncController

AJAXプログレスバーの実装には、現在のタスクのステータスを返す追加のアクションメソッドが必要になると思います。しかし、ワーカースレッドとそのアクションメソッドの間でタスクのステータスに関する情報を交換する最善の方法についてはわかりません。

これまでのところ、進行中の進捗状況に関する情報を一意のIDとともにセッション辞書に入れ、そのIDをクライアントと共有してステータスをポーリングできるようにしました。しかし、おそらく私が気付かなかったはるかに簡単な方法があります。

これを行うにはどうすればよいですか?

おかげで、

エイドリアン

+0

これは、通常の要求に対して進捗バーが表示されない理由を尋ねるようなものです。そのように考えるときは、自分自身に答えるべきです。 – nick

+2

@nick:そうではありません。通常のリクエストは長時間実行されません。最大で数秒かかる何かのためにプログレスバーは必要ありません。ただし、非同期コントローラを使用している場合は、要求に長い時間がかかることが予想されます。プログレスバーが必要な時です。私はこれを明らかにした唯一の人ですか? –

+0

Asyncコントローラを使用すると、タスクが別の場所に移動することになります。そのため、非同期にして残りのコードを引き続き実行できるようになります。長時間実行する必要はありません。つまり、パフォーマンスを向上させることができます。 Webリクエストでは、何らかのメリットがクライアントに通知されます。あなたは唯一の人ですか?それは何かを言いますか?あなたは何を期待していますか?サーバーは複数の応答を送信し続けるので、進行状況バーが表示されます。これはパフォーマンスの利点を無効にし、本当に愚かな動作を追加します。 – nick

答えて

16

非常に興味深い質問!実際には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?Cache? Session?);
  • ベスト運

など(ユーザーがブラウザを閉じた状態) クライアントが操作 を監視するために停止したとき、それは本当に手動でリソースを解放するために必要と何をすべきかです!

+0

こんにちは、あなたの詳細な答えをありがとう。それはまさに私が思いついたアプローチであり、私のOPの第3段落で説明しました。これは正常に動作しますが、ほぼすべての非同期コントローラ(つまりプログレスバー)の一部でなければならない面倒な実装のようです。私はASP.NET MVCがこれよりも優れていると思っていた(あるいは少なくとも望んでいた)だろうし、非同期コントローラのための何らかの進捗インジケータを提供していただろう。 –

+1

私は、非同期コントローラが何のために設計されているのか完全に理解していないのだろうかと疑問に思います。非同期リクエスト処理ではなく、サーバー上での長い操作の実行に関するものです。残念ながら、HTTPは同期プロトコルであり、最初からそのような目的のために設計されたものではありません。 –

+0

また、私の意見では、1つのリクエストをオープン状態にして、並列リクエストを使って進捗状況について定期的にサーバーにポーリングすることをお勧めします。 –

関連する問題