3


0

私はDoLookup()関数を持つC#を使用してASP.NET Webサービスを書いています。 DoLookup()関数を呼び出すたびに、リモートサイトのWebサービスとローカルデータベースの2つのクエリを実行するためのコードが必要です。 結果をコンパイルしてDoLookupメソッドへの応答として返すには、両方のクエリが完了している必要があります。 私が扱っている問題は、応答時間とWebサーバー上のリソース使用量の両方の観点から、これをできるだけ効率的にしたいということです。 1時間に最大数千件のクエリが発生する可能性があります。 これは私がこれまでに持っているものの大まかなC#のような概観です:

パブリッククラスSomeService:System.Web.Services.WebService {public SomeResponse DoLookup(){//リモートWebサービスでルックアップを行い、応答を取得しますWebResponse wr = RemoteProvider.DoRemoteLookup();

//ローカルデータベースでルックアップを行い、応答を取得します。DBResponse dbr = DoDatabaseLookup();

SomeResponse resp = new SomeResponse(wr、dbr);

応答を返します。 }}

上記のコードはすべてを順番に実行し、うまく機能しますが、今度はよりスケーラブルにしたいと思います。 DoRemoteLookup()関数を非同期的に呼び出すことができ(RemoteProviderにはBeginRemoteLookup / EndRemoteLookupメソッドがあります)、BeginExecuteNonQuery / EndExecuteNonQueryメソッドを使用してデータベース検索を非同期的に行うこともできます。

私の質問は(最後に)これ​​です:どのように私は別々のスレッドで同時にリモートWebサービスルックアップとデータベースルックアップの両方を起動し、それらがレスポンスを返す前に完了したことを確認するには?

両方のリクエストを別々のスレッドで実行したいのは、どちらもレスポンスタイムが長い(1または2秒)ため、レスポンスを待っている間に他のリクエストを処理するためにWebサーバーのリソースを解放したいのです。 もう1つ注意してください - 現在、リモートWebサービス検索は非同期的に実行されています。上記のサンプルをあまりにも複雑にしたくないのです。 私が苦労しているのは、リモートサービス検索とデータベース検索の両方を同時に開始し、それらがいつ完了したかを把握することです。

何か提案をありがとう。

4 Answer


2


スレッドごとに1つずつ、一対の `AutoResetEvents`を使用できます。 スレッドの実行が終了したら、AutoResetEvents.Set()を呼び出してイベントを発生させます。

スレッドを生成した後、あなたは2つのAutoResetEventと共に `WaitAll()`を使います。 これにより、両方のイベントが設定されるまでスレッドはブロックされます。

このアプローチの注意点は、Set()が確実に呼び出されるようにする必要があることです。そうしないと、永遠にブロックされます。 さらに、スレッドを使用して適切な例外処理を実行するようにします。そうしないと、意図しない例外が原因でWebアプリケーションが再起動されたときに、誤ってパフォーマンスの問題が発生する可能性があります。

http://msdn.microsoft.com/ja-jp/library/system.threading.autoresetevent.aspx[MSDN AutoResetEventの使用法に関するサンプルコードがあります。


1


http://msdn.microsoft.com/ja-jp/library/bb552861.aspx[Asynchronous XML Webサービスメソッド]、 http://msdn.microsoft.com/ja-jp/library/bb552861.aspx[How to [非同期Webサービスメソッドを作成する]および http://msdn.microsoft.com/ja-jp/library/bb552861.aspx[How to:Webサービスメソッドを使って非同期呼び出しを連鎖する]を参照してください。

しかし、それらの記事の最初の段落に注意してください。

このトピックはレガシーテクノロジーに固有のものです。 XML WebサービスおよびXML Webサービスクライアントは、 Windows Communication Foundation(WCF)を使用して作成する必要があります。 __

'' '' '

ところで、これらの記事が示すように物事を行うことは重要です。長期実行タスクの実行中にASP.NETワーカースレッドを解放するためです。 そうでなければ、ワーカースレッドをブロックし、それ以上のリクエストを処理できなくなり、スケーラビリティに影響を与える可能性があります。


0


Webリクエストとデータベース検索の両方にコールバック関数を使用できると仮定すると、これらの行に沿って何かがうまくいくかもしれません

bool webLookupDone = false; bool databaseLookupDone = false;

private void FinishedDBLookupCallBack(){databaseLookupDone = true; if(webLookupDone){FinishMethod(); }}

private void FinishedWebLookupCallBack(){webLookupDone = true;} if(databaseLookupDone){FinishMethod(); }}


0


私は、投票するためにもコメントするために十分な担当者がいないと思います。 つまり、これはJohn Saundersの回答とAlanのそれに対するコメントです。

スケーラビリティとリソースの消費を心配しているのなら、間違いなくJohnの答えを取り入れたいと思うでしょう。

ここで2つの考慮事項があります:個々の要求をスピードアップすること、そしてあなたのシステムが多くの同時要求を効率的に扱うようにすること。 前者のAlanとJohnの両方の答えは、外部呼び出しを並行して実行することによって達成されます。

後者は、それがあなたの主な関心事だったように思えますが、どこにもスレッドをブロックしないことによって達成されます。 ジョンの答え

あなた自身のスレッドを生成しないでください。 スレッドは高価です、そして、あなたがあなたによってあなたのためにあなたのためのあなたのための外部呼び出しを扱うスレッドを処理するスレッドが既にたくさんあります .net framework.

あなたのサービスのWebメソッドも同様に非同期である必要があります。 そうでなければ、ワーカースレッドはあなたの外部呼び出しが行われるまでブロックされます(たとえそれらが並行して実行されたとしてもそれはまだ1-2秒です)。 また、着信要求を処理するCPUあたり12スレッドしかありません(machine.configが 推奨に従って設定されている場合)。 あなたはせいぜい12の同時要求(CPUの数の倍数)を処理することができるでしょう。 一方、あなたのWebメソッドが非同期の場合、Beginはほぼ瞬時に戻り、別の着信要求を処理する準備ができているスレッドはワーカースレッドプールに戻ります。 IOスレッドプールから戻ったときに、スレッドによって処理されます。