我有一个易趣帐户。为了方便地更新我的产品,我在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);
}
我知道,单独发送所有请求太糟糕了,因为每个请求都有自己的标题等等......这样效率不高。
嗯,这样做的正确方法是什么?
答案 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
中删除线程并启动另一个排队的线程。一旦Queue
和Dictionary
为空,您就完成了。
如果您将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
我认为这是正确的方法