0

私はeBayアカウントを持っています。製品の更新を簡単にするために、C# で Windows サービスを作成しました。FileSystemWatcherxml ファイルを(によって) 待機し、ファイルが表示されると、サービスがそれを読み取り、API を介して eBay サーバーに要求を送信します。ファイルには、約 1000 ~ 3000 行が含まれる場合があります。

以前は、高速化するために12 個のスレッドを作成していました。なぜ12スレッドを選んだのかわかりませんが、多すぎず少なすぎず、十分な量だと思いました。

だからここに私が以前のように見えた方法があります(少し汚い、12は定数でなければなりません)

private static void UpdateAsync(IEnumerable<ProductInfo> products)
        {
            ProductInfo[] productsInfo = items.ToArray();
            Thread[] threads = new Thread[12];
            bool sendPartialy = productsInfo .Length > 12;
            int delta = 0;
            for (int i = 0; i < productsInfo.Length; i++)
            {
                if (sendPartialy )
                {
                    if (i != 0 && i % 12 == 0)
                    {
                        WaitForExecutedThreads(threads);
                        delta = 12 * (i / 12);
                    }
                }

                ProductInfo product = ProductInfo[i];
                threads[i - delta] = new Thread(_ => product.UpdateItem(context));
                threads[i - delta].Start();
            }

            WaitForExecutedThreads(threads);
        }

次に、ネットワーク インターフェイスが1 つしかないため、スレッドを使用する必要がないことを教えてくれました。同時に 12 個の https 要求を実行できるようにするのは狭いため、各スレッドは別のスレッドを待機することになります。

そのため、マルチスレッドをまったく使用せず、次のような単純なリクエストのみを使用することにしました。

    var itemInfoLights = new List<ItemInfoLight>();
    foreach (var p in productsInfo )
    {
       p.UpdateItem(context);
    }

それぞれが独自のヘッダーなどを持っているため、すべてのリクエストを個別に送信するのは残念です...それは効率的ではありません。

さて、それを行うための正しいアプローチは何ですか?

4

5 に答える 5

3

スレッドを開始するコストは、Web サービス呼び出しを実行する時間と比較して取るに足らないものです。私にとってうまくいったのは、Web サービス呼び出しが完了するとコールバックを呼び出すワーカー メソッドを使用して、送信する要求ごとQueueにインスタンスを作成することです。Threadスレッドは、インスタンス化されたばかりのときではなく、開始時にのみリソースを消費します。

Dictionary次に、スレッドをキューから取り出して開始し、スレッドによってキー付けされた に追加するスーパーバイザ クラスを使用しますManagedThreadId。これは、最大同時接続数 12 に達するまで繰り返されます。各スレッドが終了すると、スーパーバイザにコールバック メソッドが呼び出され、スーパーバイザはそのスレッドを から削除して、Dictionaryキューに入れられた別のスレッドを起動します。QueueDictionaryが空になったら完了です。

UI アプリをサービスに接続すると、スループットとキューに入れられたアクティブなスレッドを監視しながらスレッド制限を調整できるため、リアルタイムで操作できます。

またmaxconnection、app.config のプロパティを 100 などに設定して、実験する余地を与える必要があります。

于 2012-10-04T23:02:22.247 に答える
3

このネットワーク操作中は CPU を必要としないため、新しいスレッドを作成することは最適な選択ではありません。(CPU が実際の問題である場合、通常はプロセッサごとに 1 つのスレッドのみが必要です。したがって、2 つまたは 4 つのスレッドが理想的です。)

メソッドの非同期バージョンがある場合は、UpdateItem更新する項目があれば何度でも呼び出すことができ、コールバック関数で完了を処理できます。実際には何もしないスレッドを開始しないため、これははるかに効率的ですが、ほぼ同時に複数のリクエストを実行することになります。

メソッドの非同期バージョンがない場合、スレッドを使用することが、並列更新呼び出しを取得する唯一の簡単な方法になります。代わりに使用できますThreadPool.QueueUserWorkItem。これは、すでに利用可能なスレッドを利用して、毎回新しいスレッドをスピンアップするコストを回避します。

于 2012-10-04T17:40:39.903 に答える
2

最大の効率が必要だと思うので、 を使用することをお勧めします。ネット スレッド プールThreadPoolPCから最大スレッドを割り当てるクラスがあります。ウェブ上には多くの例があります。

ここにそれらの1つ。msdn と例

ThreadPool.QueueUserWorkItem(YourRequestFunctionName, parameterObject);

于 2012-10-04T17:33:22.097 に答える
1

**only one** network interface部分の意味がわかりません。悪いアドバイスのように聞こえます。

ブラウザでさえ、さまざまな部分 (css、javascript、画像、ページ自体など) を取得するために Web ページをプルダウンするときに、通常 5 ~ 10 の同時要求を発行します。したがって、12 個のスレッドがあれば問題ないはずです。

ヘッダーなどに関しては、個々のリクエストでそれを避けることはできません。他の唯一の方法は、API が単一のトランザクションで複数のリクエストを送信できる場合です。私は eBay API に詳しくありませんが、サポートしていると思います。

ヒントについては、この質問を参照してください:複数のアイテムの CompleteSale Ebay API

于 2012-10-04T17:29:27.550 に答える
0

このようなことをするときは、非同期の HttpRequest メソッドを使用しますが、それは私にとってはうまくいきます。HttpWebRequest.BeginGetResponse と HttpWebRequest.BeginGetRequestStream を調べてください。

また、詳細情報: http://msdn.microsoft.com/en-us/library/86wf6409(VS.71).aspx

これは正しいアプローチだと思います

于 2012-10-04T17:29:31.367 に答える