如何同时发送多个http请求?

时间:2012-10-04 17:23:29

标签: c# .net multithreading web-services windows-services

我有一个易趣帐户。为了方便地更新我的产品,我在C#中创建了一个Windows服务。它等待(FileSystemWatcher)xml文件,一旦出现文件,服务就会读取它并通过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);
        }

然后他们告诉我,由于只有一个网络接口,因此不需要使用线程:它允许同时执行12个https请求,因此每个线程都在等待另一个。

这就是为什么我决定不使用多线程,只是使用这样的简单请求:

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

我知道,单独发送所有请求太糟糕了,因为每个请求都有自己的标题等等......这样效率不高。

嗯,这样做的正确方法是什么?

5 个答案:

答案 0 :(得分:3)

由于在此网络操作期间不需要CPU,因此创建新线程不是最佳选择。 (当CPU是实际问题时,通常每个处理器只需要1个线程。因此,2或4个线程将是理想的。)

如果你有UpdateItem方法的异步版本,你可以多次调用它来更新项目,然后在回调函数中处理完成。这样会更有效率,因为你不会启动那些没有真正做任何事情的线程,但是你几乎会同时执行多个请求。

如果您没有该方法的异步版本,使用线程将是获得并行更新调用的唯一简便方法。您可以改用ThreadPool.QueueUserWorkItem。这利用了已经可用的线程,避免了每次启动新线程的成本。

答案 1 :(得分:2)

因为我猜你想要最高效率,所以我建议你使用。 Net Thread Pool 。有ThreadPool类将从pc分配最大线程。网上有很多例子。

one of them here. msdn with example

ThreadPool.QueueUserWorkItem(YourRequestFunctionName,parameterObject);

答案 2 :(得分:2)

与执行Web服务调用的时间相比,启动线程的成本微不足道。对我来说有用的是Queue一个Thread实例,用于使用工作方法发送的每个请求,该方法在Web服务调用完成后调用回调。线程只在它们启动时消耗资源,而不是在它们刚刚被实例化时消耗。

然后我使用一个主管类,它使一个线程出列,启动它,然后将它添加到由线程'Dictionary键入的ManagedThreadId。重复此过程,直到达到最大12个并发连接数。当每个线程完成时,它会将回调方法调回给主管,然后主管从Dictionary中删除线程并启动另一个排队的线程。一旦QueueDictionary为空,您就完成了。

如果您将UI应用程序连接到服务,则可以在监视吞吐量以及排队和活动线程的同时调整线程限制,以便您可以实时使用它。

您还应该将app.config中的maxconnection属性设置为100,以便为您提供实验空间。

答案 3 :(得分:1)

我不确定**only one** network interface部分是什么意思。听起来像是一些不好的建议。

甚至浏览器在下拉网页时通常会发出5到10个同时发出的请求,以便抓取各个部分(css,javascript,图像,页面本身......)。所以,有12个线程应该没问题。

关于标题等,您无法避免单个请求。唯一的另一种方法是API允许您在单个事务中发送多个请求。我不熟悉eBay API,但我想他们会支持它。

您可以查看此问题以获取提示:CompleteSale Ebay API for multiple items

答案 4 :(得分:0)

当我做这样的事情时,我使用异步HttpRequest方法,它适用于我。查看HttpWebRequest.BeginGetResponse和HttpWebRequest.BeginGetRequestStream。

还有更多信息:http://msdn.microsoft.com/en-us/library/86wf6409(VS.71).aspx

我认为这是正确的方法