【发布时间】:2015-08-09 21:33:28
【问题描述】:
我正在尝试尽可能快速高效地轮询 API 以获取市场数据。 API 允许您根据请求从 batchSize 市场获取市场数据。 API 允许您有 3 个并发请求,但不能有更多(或引发错误)。
我可能会请求来自多个不同市场的batchSize 数据。
我不断循环遍历所有的市场,分批请求数据,每个线程一个批次,任何时候三个线程。
市场的总数(以及批次)可以随时变化。
我正在使用以下代码:
private static object lockObj = new object();
private void PollMarkets()
{
const int NumberOfConcurrentRequests = 3;
for (int i = 0; i < NumberOfConcurrentRequests; i++)
{
int batch = 0;
Task.Factory.StartNew(async () =>
{
while (true)
{
if (markets.Count > 0)
{
List<string> batchMarketIds;
lock (lockObj)
{
var numBatches = (int)Math.Ceiling((double)markets.Count / batchSize);
batchMarketIds = markets.Keys.Skip(batch*batchSize).Take(batchSize).ToList();
batch = (batch + 1) % numBatches;
}
var marketData = await GetMarketData(batchMarketIds);
// Do something with marketData
}
else
{
await Task.Delay(1000); // wait for some markets to be added.
}
}
}
});
}
}
即使在临界区有锁,每个线程都以 batch = 0 开始(每个线程经常轮询重复数据)。
如果我将批处理更改为私有 volatile 字段,则上述代码将按我的意愿工作(易失性和锁定)。
所以由于某种原因我的锁不起作用?我觉得这很明显,但我错过了。
我认为这里最好使用锁而不是 volatile 字段,这也正确吗?
谢谢
【问题讨论】:
-
请澄清您的问题。我不明白有什么不清楚的。你在多个线程之间共享一个变量,你说
volatile解决了你的问题。 -
@YuvalItzchakov volatile + lock 解决了问题,但我相信单独一个锁就足够了吗?
-
lockObj 是在哪里定义的?
-
@JamesBrierley 添加了 lockObj 定义
-
在for循环外定义批处理是否有效?
标签: c# multithreading task-parallel-library task semaphore