データベースに履歴結果をバッチで照会するサービスがあります。 バッチは、開始時刻と終了時刻に基づいています。すべてのバッチ間のデータは相互に排他的です。したがって、バッチのセットでは、任意の順序で実行できます。一部のバッチは他のバッチよりも実行に時間がかかります。いずれかのバッチが失敗した場合は、プロセス全体が中止/中止され、エラーが記録されます。データをクライアントに返すときは、すべてのバッチのデータを結合する必要があります。
問題:
できるだけ早くデータをクライアントに返します。
初期ソリューション:
当初、私は同期の順序でバッチを実行していました。これは、データが相互に排他的であるという事実を利用していませんでした。最初の使用後、このロード方法が長すぎることが判明しました。いくつかのデバッグの後、私は遅いの主な原因がSQLクエリの実行時間であることを発見した。したがって、次の解決策は、BeginExecuteReader()
とEndExecuteReader()
を使用して、各バッチを非同期に実行しようとすることでした。すべてのバッチを非同期に呼び出した後、サービスはwhileループで待機し、300ミリ秒ごとにポーリングして、いずれかのクエリーが完了したかどうかを確認します。そうだったら、それは読まれるでしょう。
int batchCount = 0, resultCount = 0;
List<AsyncDataResult> asyncCalls = new List<AsyncDataResult>();
while (true)
{
if (asyncCalls.Count == 0)
{
break;
}
if ((asyncCalls[resultCount]).AsyncResult.IsCompleted)
{
ReadAsyncResultsFromDb(asyncCalls[resultCount]);
asyncCalls.RemoveAt(resultCount);
}
resultCount++;
if (resultCount >= asyncCalls.Count)
{
resultCount = 0;
Thread.Sleep(300);
}
}
上記のアプローチは、ポーリングが実際にローディング遅延に加算され、大規模なデータセットのために、非常に小さなデータセットに(多くのバッチを横切って)ロード時間を減少させました。
質問:
- がどのように私は非同期的にSQLを実行しますが、ポーリングをしませんか?
- 完了するとすぐに各バッチを読み始めますか?
更新: このことについて申し訳ありませんが、私は、私は非同期呼び出しを呼び出しているのと同じ方法で返す必要がある部分を追加するのを忘れ。この理由は、データを取り込む必要があるデータセットが、このメソッドのパラメータとして渡されるためです。 begin readerのIAsyncCallback
を使用すると、クラス全体を変更する必要があります。私はそれをする必要はないと思っていた。
どのネットフレームワーク4? –
はい。その.net 4.0 – EndlessSpace