asp.netで複数のwebrequestsが非同期に?
-
05-07-2019 - |
質問
4つの異なるWebリクエストからのデータを単一のアイテムリストに結合する必要があるページがあります。現在、これらを順番に実行し、1つのリストに追加してから、そのリストをリピーターにバインドしています。
ただし、これら4つのwebrequestsを非同期で呼び出して、同時に実行してロード時間を節約できるようにしたいと思います。残念ながら、私が見たすべての非同期チュートリアルと記事は、単一のリクエストを処理し、finishedハンドラーを使用して処理を続行します。
各結果を単一のリストに入れる必要があることを念頭に置いて、4つ(これはさらに増えるかもしれません!)を同時に実行するにはどうすればよいですか?
どうもありがとう!
編集:私がやっていることの簡単な例:
var itm1 = Serialize(GetItems(url1));
list.AddRange(itm1);
var itm2 = Serialize(GetItems(url2));
list.AddRange(itm2);
string GetItems(string url)
{
var webRequest = WebRequest.Create(url) as HttpWebRequest;
var response = webRequest.GetResponse() as HttpWebResponse;
string retval;
using (var sr = new StreamReader(response.GetResponseStream()))
{ retval = sr.ReadToEnd(); }
return retval;
}
解決
最終データは4つのリクエストすべての結果に依存するため、これは非常に簡単です。
できることは、それぞれが適切なWebメソッドを指す4つの非同期デリゲートを作成することです。それらすべてに対してBeginInvokeを実行します。そして、WaitHandleを使用してすべてを待ちます。 Webメソッドの処理中に続行するのではなく、すべてのWebメソッドの実行が完了するまで待機するため、コールバックを使用する必要はありません。
すべてのWebメソッドが実行された後にのみ、waitステートメントの後のコードが実行されます。ここで、4つの結果を組み合わせることができます。
これは、私が開発したサンプルコードです。
class Program
{
delegate string DelegateCallWebMethod(string arg1, string arg2);
static void Main(string[] args)
{
// Create a delegate list to point to the 4 web methods
// If the web methods have different signatures you can put them in a common method and call web methods from within
// If that is not possible you can have an List of DelegateCallWebMethod
DelegateCallWebMethod del = new DelegateCallWebMethod(CallWebMethod);
// Create list of IAsyncResults and WaitHandles
List<IAsyncResult> results = new List<IAsyncResult>();
List<WaitHandle> waitHandles = new List<WaitHandle>();
// Call the web methods asynchronously and store the results and waithandles for future use
for (int counter = 0; counter < 4; )
{
IAsyncResult result = del.BeginInvoke("Method ", (++counter).ToString(), null, null);
results.Add(result);
waitHandles.Add(result.AsyncWaitHandle);
}
// Make sure that further processing is halted until all the web methods are executed
WaitHandle.WaitAll(waitHandles.ToArray());
// Get the web response
string webResponse = String.Empty;
foreach (IAsyncResult result in results)
{
DelegateCallWebMethod invokedDel = (result as AsyncResult).AsyncDelegate as DelegateCallWebMethod;
webResponse += invokedDel.EndInvoke(result);
}
}
// Web method or a class method that sends web requests
public static string CallWebMethod(string arg1, string arg2)
{
// Code that calls the web method and returns the result
return arg1 + " " + arg2 + " called\n";
}
}
他のヒント
各リクエストを独自のスレッドで起動し、結果をリストに追加する方法はどうですか?
次のコードをテストできます:
Parallel.Invoke(()=&gt;
{
// TODOリクエストを実行します...
});
参照並列拡張機能が必要です: http://msdn.microsoft.com/en-us/concurrency/bb896007。 aspx
@Josh:4つ(可能性としてはそれ以上)の非同期要求を送信し、応答を追跡する(たとえば、リストにフィードする)ことに関する質問について。 4つの要求と4つの応答ハンドラーを作成できますが、より多くの要求がある可能性があるため、非同期ループを作成できます。古典的なforループは、init、条件、および増分で構成されています。古典的なforループをwhileループに分解しても、同等のものを使用できます。次に、whileループを再帰関数に作成します。これで、非同期にすることができます。ここにいくつかのサンプルスクリプトを http://asynchronous.me/ に置きます。あなたの場合、オプションでforループを選択します。リクエストを順番に送信する場合、つまり、前のレスポンス(request1、response1、request2、response2、request3、response3など)の後に1つのリクエストを送信する場合は、シリアル通信(シーケンシャル)を選択しますが、コードはもう少し複雑。一方、応答が受信される順序(ランダムな順序)を気にしない場合は、並列通信(同時)を選択すると、コードはより直感的になります。どちらの場合でも、各応答は識別子(単純な整数)によって対応する要求に関連付けられるため、それらすべてを追跡できます。このサイトでは、サンプルスクリプトを提供します。サンプルはJavaScriptで記述されていますが、どの言語にも適用できます。スクリプトを言語とコーディング設定に適合させます。このスクリプトを使用すると、ブラウザーは4つの要求を非同期的に送信し、識別子によって、応答が対応する要求を追跡できます。お役に立てれば。 / Thibaud Lopez Schneider