10

asp.net(mvc)Webサイトがあります。関数の一部として、たとえば次のような長時間実行される操作をサポートする必要があります。

ユーザーから開始:ユーザーは(xml)ファイルをサーバーにアップロードできます。サーバー上でファイルを抽出したり、操作(データベースに挿入)などを行う必要があります...これには1分から10分かかる場合があります(またはそれ以上-ファイルサイズによって異なります)。もちろん、インポートの実行中にリクエストをブロックしたくはありませんが、ユーザーを進行状況ページにリダイレクトして、ステータスやエラーを確認したり、インポートをキャンセルしたりすることができます。

この操作は頻繁には使用されませんが、2人のユーザーが同時にデータをインポートしようとする場合があります。インポートを並行して実行すると便利です。最初は、iis(コントローラーアクション)で新しいスレッドを作成し、新しいスレッドでインポートを実行することを考えていました。しかし、これが良いアイデアかどうかはわかりません(Webサーバー上に作業スレッドを作成するため)。Windowsサービスまたは他のアプローチを使用する必要がありますか?

システムから開始:-新しいデータでluceneインデックスを定期的に更新する必要があります。-(将来的には)大量のメールを送信する必要があります。

これをサイトのジョブとして実装し、Quartz.netを介してジョブを実行する必要がありますか、それともWindowsサービスなども作成する必要がありますか?

サイトの「ジョブ」を実行する場合のベストプラクティスは何ですか?

ありがとう!

4

3 に答える 3

7

長時間実行されるタスクには、スタンドアロンの Windows サービスを実装します。Web アプリケーションは、長時間実行されるタスクをキュー アプローチを介してこのサービスに委任します。タスク キューをどのように整理するかは、あなた次第です。キューに入れられたタスクに優先度、最大実行時間があるかどうか。キューは、ジョブ実行ステータス情報プロパティを含む DBMS の通常のテーブルとして実装できます (非常に簡単な方法)。

したがって、一般的なシナリオは次のようになります。

  • クライアントは必要なすべての情報を Web サーバーに送信します

  • Web サーバーはタスクをサービスに委任し、クライアントに通知します - タスクは正常にキューに入れられました (タスク ID もクライアントに送信されます)

  • 外部サービスがタスク処理を開始し、進捗情報を更新します。

  • クライアントは、ジョブ (以前に受け取った ID を持つ) のステータスと進行状況に関する短い実行要求で Web サーバーのポーリングを開始します。

さまざまなテクノロジ (Windows サービス + DB / WCF サービス) とさまざまな通信アプローチ (ポーリング、プッシュ、コールバック) を選択できますが、長時間実行されるタスクを外部サービスに委任することをお勧めします (Web アプリ内で実行しないでください)。

長時間実行されるタスクを実行すると、(マルチスレッド プログラミング用語で) 要求ごとのスレッド モデルが実現します。このモデルにはスケーラビリティが低く、スレッド プールの最大スレッド数の制限があります。それはあなたの場合ではありません:)

于 2010-05-11T07:18:42.280 に答える
4

私の意見では、長時間実行されるタスクは通常、常に非 UI ベースの操作に委任する必要があります。おそらくWFまたはウィンドウサービスをお勧めします。

于 2010-05-11T07:14:40.030 に答える
1

jQuery を使用して、これに似たシナリオを正常に実装しました。基本的に、私はbeforeSend: 関数を使用して「お待ちください」タイプのページを表示します。これがプレイ中の基本的なコードです(そうではありません。AsyncController基本クラスを使用してアクションを非同期にすることもできます):

<script type="text/javascript">
    $(document).ready(function() {
        $('#create').bind('click', function() {
            saveFundProperty();
        });
    });

    // main functions
    function saveFundProperty() {
        var url = '<%= Url.Action("Create", "FundProperty") %>';
        var params = { fundId: $("#FundID").val(), propertyId: $("#PropertyID").val() };
        SendAjax(url, params, beforeQuery, saveFundPropertyResponse);
    }

    function beforeQuery() {
        var url = '<%= Url.Action("Wait", "FundProperty") %>';
        $("#statusMsg").load(url);
    }

    function saveFundPropertyResponse(data) {
        if (data.length != 0) {
            if (data.indexOf("ERROR:") >= 0) {
                $("#statusMsg").html(data).css('backgroundColor','#eeaa00');
            }
            else {
                $("#statusMsg").html(data);
            }
        }
    }
</script>

お役に立てれば。

このSendAjaxメソッドは、物事をもう少し一貫させるための純粋なラッパー関数です。ここに完全です:

<script type="text/javascript">
function SendAjax(urlMethod, jsonData, beforeSendFunction, returnFunction, dataType, contentType) {
    $.ajaxSetup({ cache: false });
    dataType = dataType || "text"; // default return type
    contentType = contentType || "application/x-www-form-urlencoded"; // default input type
    $.ajax({
        type: "POST",
        url: urlMethod,
        data: jsonData,
        dataType: dataType,
        contentType: contentType,
        beforeSend: function() {
            if(beforeSendFunction!==null)
                beforeSendFunction();
        },
        success: function(data) {
            // Do something interesting here.
            if (data != null && returnFunction!==null) {
                returnFunction(data);
            }
        },
        error: function(xhr, status, error) {
            // Boil the ASP.NET AJAX error down to JSON.
            var err = eval("(" + xhr.responseText + ")");

            // Display the specific error raised by the server
            alert(err.Message);
        }
    });
}
</script>

[編集] - SendAjax フォーマットで何が起こっているのかわかりません。簡単にコピー/貼り付けできることを願っています...

于 2010-05-11T08:26:56.950 に答える