2

私は、いくつかのレガシー技術に基づいて構築されたカスタム ID カード プリンターのフロント エンドとして機能する MVC 3 Web アプリケーション (.NET Framework 4、IIS7) に取り組んでいます。詳細には入りませんが、[印刷] をクリックすると、Web アプリはカード情報を含む行をデータベースに書き込み、戻ります。次に、バックエンドのサービスが行を取得し、カードの実際の印刷を処理します。バックエンド サービスが完了すると、成功または失敗を示すステータス列で行が更新されます。

現在、アプリケーションは (jquery ajax を介して) データを POST し、行がデータベースに書き込まれると、コントローラーはユーザーに表示される成功を返します。私が説明したセットアップのため、サービスまたはカード プリンターに問題がある可能性があるため、これは実際に現実を反映している場合と反映していない場合があります。

サービスからの行への更新に基づいて、UI が更新を「待機」するか、成功または失敗するようにするという新しい要件があります。jquery ajax 呼び出しを介してクライアント側で非同期の方法で既にセットアップされており、フロントエンドでの処理については心配していません。私はSignalRなどを見て、この部分をカバーしました。

私が探しているのは、Web サーバー側で正しく処理する方法に関する情報 (解決策ではなく、リンクと記事) です。以前のリクエストから定期的にデータベースをポーリングしている間、着信リクエストをブロックして印刷したくありません。大まかに言うと、コントローラーと必要なバックグラウンド プロセスをセットアップするための最善の方法は何かを知りたいと思います。

  1. リクエストを受け入れ、行をデータベースに書き込みます
  2. バックグラウンド ポーリング プロセスをセットアップし、制御を ASP.net に戻します。
  3. 行が更新されるまで (またはタイムアウトに達するまで) データベースを頻繁にポーリングする
  4. クライアントに答えを返す

私はスレッディングの専門家ではありませんが、これが間違って行われると危険な領域にいることを十分に知っています. どんな助けでも大歓迎です。

4

2 に答える 2

1

コメントしますが、十分な担当者がいません。

サーバーが UI にプッシュすることに注目するのはなぜですか? フォームが行をデータベースに書き込み、「成功」を画面に表示すると言いますが、これは実際のステータスではない可能性があります。印刷プロセス中の任意の時点で、データベースにクエリを実行して最新のステータスを見つけることができますか?

UI がページのセクションを X 秒ごとに最新のステータスで更新するのを妨げているものはありますか? サーバーが情報をプッシュするのではなく、UI に情報をプルさせます。

データベースからのログ レコードを表示するページがあります。毎日、より多くのレコードをログに書き込むプロセスが開始されるため、プロセスを監視する自動更新機能があると便利です。そのページには、部分ビューで新しいテーブルを出力するコントローラーに要求を行う Ajax フォームがあります。UpdateTargetIdこの部分ビューは、Ajax フォームの に入れられます。自動更新のために、javascriptsetInterval()関数を使用して X 秒ごとに Ajax フォームを送信します。OnSuccess特定の戻り条件を確認できる場所など、指定できる追加のコールバックもあります。

Ajax.BeginForm の AjaxOptions クラス

フォーム例

w3schools の setInterval()

于 2013-01-30T21:36:47.857 に答える
0

これが私がやった方法の擬似コードです。追加の着信リクエストをブロックせず、複数の同時リクエストで正しく動作することをテストしました。これはtask.Wait()でブロックされますが、負荷がかかっている場合、スレッドプールが正しく構成されていないと、パフォーマンスの問題が発生すると思います。merekelへの私のコメントによると、最終的には、このようにするのではなく、クライアント側のポーリングソリューションを使用することになります。

public class MyController : AsyncController 
{
    public void SaveAndPrintAsync(CardData data)
    {
        if (data == null)
            throw new ArgumentNullException("data", "data cannot be null");

        // 1. Accept the request and write the row to the database
        var result = _databaseFacade.Save(data);
        AsyncManager.Parameters["result"] = result;

        // 2. set up a background polling process, then return control to ASP.net
        AsyncManager.OutstandingOperations.Increment();
        var task = _databaseFacade.GetPrintStatusAsync(data);
        task.ContinueWith(t =>
        {
            AsyncManager.OutstandingOperations.Decrement();
        });
        task.Wait();
        AsyncManager.Parameters["status"] = task.Result;
    }

    public JsonResult SaveAndPrintCompleted(PrintResult result, PrintStatus status)
    {
        try // return an answer to the client
        {  
            if (status == PrintStatus.Printed)
                return Json(result);

            throw new ApplicationException("An error occurred while printing. Please try again.");
        }
        catch (Exception ex)
        {
            return FormatError(ex); // returns Json
        }
    }
}

public class DatabaseFacade 
{
    public Task<PrintStatus> GetPrintStatusAsync(CardData data)
    {
       var task = Task.Factory.StartNew(() =>
           {
               var counter = 0;
               var status = PrintStatus.Waiting;
               do
               {
                   ++counter;
                   var queue = _myDBContext.FindById<CardData>(data.ID);

                   if (queue != null)
                       status = (PrintStatus)Enum.Parse(typeof (PrintStatus), queue.PrintStatus.ToString());

                   if (status == PrintStatus.Waiting || status == PrintStatus.Printing)
                       Thread.Sleep(1000);

               } while (counter < 5 && (status == PrintStatus.Waiting || status == PrintStatus.Printing));
               return status;
           }, TaskCreationOptions.LongRunning);
       return task;
    }
}
于 2013-01-30T23:31:03.960 に答える