0

我有一个 eBay 帐户。为了轻松更新我的产品,我用 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);
    }

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

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

4

5 回答 5

3

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

如果您有该UpdateItem方法的异步版本,则可以根据要更新的项目多次调用它,然后在回调函数中处理完成。这会更有效率,因为您不会启动实际上不做任何事情的线程,但您将几乎同时执行多个请求。

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

于 2012-10-04T17:40:39.903 回答
3

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

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

If you wire a UI app to your service you can adjust the thread limit while monitoring your throughput and the queued and active threads so you can play with it in real-time.

You should also set the maxconnection property in your app.config to something like 100 to give you room to experiment.

于 2012-10-04T23:02:22.247 回答
2

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

其中之一在这里。msdn 举例

ThreadPool.QueueUserWorkItem(YourRequestFunctionName, parameterObject);

于 2012-10-04T17:33:22.097 回答
1

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

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

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

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

于 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 回答