5

シンプルだが時間のかかる操作があります。ユーザーがボタンをクリックすると、データベース集約的な操作が実行され、インポート テーブルから他の複数のテーブルにレコードが処理され、一度に 1 つのインポート レコードが処理されます。操作をトリガーするボタンのあるビューがあり、操作の最後にレポートが表示されます。

操作が処理されていることをユーザーに通知する方法を検討しています。これが私が気に入った解決策です。

MVC での非同期操作についてオンラインで読んでいます。プロセスが CPU にバインドされている場合は、同期操作を使用することに固執するという多くのリンクを見つけました。データベース関連のプロセスは CPU バウンドと見なされますか?

また、非同期操作ルートを取得した場合は、ここで説明されているように AsyncController を使用するか、前述の例とここでもTask を使用する必要があります。またはそれらはすべて同じですか?

4

3 に答える 3

3

最初に知っておく必要があるasyncのは、HTTP プロトコルは変更されないということです。私のブログで説明しているように、HTTP プロトコルは各要求に対して 1 つの応答を返します。そのため、一度「進行中」と言って戻ってきて、後で「完了」と言って戻ることはできません。

簡単な解決策は、完了したときにのみ戻り、AJAX を使用してクライアント側で「進行中...」の通知を投げ、要求が完了したときにページを更新することです。もっと複雑にしたい場合は、SignalR のようなものを使用して、要求が完了したときにサーバーからクライアントに通知することができます。

特に、asyncMVC アクションは「早期」に戻りません。ASP.NET は、すべての非同期アクションが完了するまで待機してから、応答を送信します。asyncサーバー側のコードは、応答性ではなく、スケーラビリティがすべてです。

そうは言っても、私は通常、サーバー側で非同期コードをお勧めします。1 つの例外は、DB バックエンドが 1 つしかない場合です (このブログ投稿で詳しく説明されています)。バックエンドが DB クラスターまたは分散型/NoSQL/SQL Azure DB である場合は、非同期にすることを検討する必要があります。

サーバーを非同期にすることに決めた場合は、単にTasks を返します。AsyncController最近は下位互換性のためにあります。

于 2013-02-20T03:43:24.513 に答える
3

C# 5.0 を想定すると、次のようになります。

// A method to get your intensive dataset
public async Task<IntensiveDataSet> GetIntensiveDataSet() {
   //in here you'll want to use any of the newer await Async calls you find 
   // available for your operations. This prevents thread blocking.

    var intensiveDataSet = new IntensiveData();
    using (var sqlCommand = new SqlCommand(SqlStatement, sqlConnection))
        {
            using (var sqlDataReader = await sqlCommand.ExecuteReaderAsync())
            {
                while (await sqlDataReader.ReadAsync())
                {
                    //build out your intensive data set.
                }
            }
        }
    return intensiveDataSet;
}


// Then in your controller, some method that uses that:
public async Task<JsonResult> Intense() {
    return Json(await GetIntensiveDataSet());
}

JS では、次のように呼び出します (JQuery を使用):

$.get('/ControllerName/Intense').success(function(data) {
   console.log(data);
});

正直なところ、実行中にある種のスピナーを表示するだけでした。

ユーザーへの何らかのフィードバックが必要な場合は、非同期呼び出し全体でユーザーのセッションに更新を振りかける必要があります...そのためには、そのセッションへの参照を渡す必要があります。次に、Session 変数内のメッセージをチェックし、一定間隔で JQuery を使用してポーリングする単純な JsonResult アクションをもう 1 つ追加するだけです。やり過ぎのようですが。ほとんどの場合、単純な「これには時間がかかる場合があります」で十分です。

于 2013-02-20T02:35:25.997 に答える
0

AJAXを使用して非同期化を実装するオプションを検討する必要があります。クライアントの「...処理中」メッセージをビュー内で最小限の手間で処理できます。

$.ajax({
    url: @Url.Action("ActionName"),
    data: data
}).done(function(data) {
    alert('Operation Complete!');
});

alert('Operation Started');

// Display processing animation

サーバー側で非同期呼び出しを処理することは、費用がかかり、複雑で、不必要になる可能性があります。

于 2013-02-20T02:13:44.050 に答える