我有一個方法Limit(),它在一定的時間內通過思考某個通道的帶寬,並通過使用Thread.Sleep()(如果達到帶寬限制)來限制它。 方法本身產生正確的(在我看來結果),但Thread.Sleep沒有(由於多線程的CPU使用),因爲我有適當的「毫秒toWait」,但速度檢查後,遠不是我已經通過的限制。Thread.Sleep的精確替代方法
有沒有辦法讓限制更精確?
限制器類
private readonly int m_maxSpeedInKbps;
public Limiter(int maxSpeedInKbps)
{
m_maxSpeedInKbps = maxSpeedInKbps;
}
public int Limit(DateTime startOfCycleDateTime, long writtenInBytes)
{
if (m_maxSpeedInKbps > 0)
{
double totalMilliseconds = DateTime.Now.Subtract(startOfCycleDateTime).TotalMilliseconds;
int currentSpeedInKbps = (int)((writtenInBytes/totalMilliseconds));
if (currentSpeedInKbps - m_maxSpeedInKbps > 0)
{
double delta = (double)currentSpeedInKbps/m_maxSpeedInKbps;
int millisecondsToWait = (int)((totalMilliseconds * delta) - totalMilliseconds);
if (millisecondsToWait > 0)
{
Thread.Sleep(millisecondsToWait);
return millisecondsToWait;
}
}
}
return 0;
}
測試類,它總是在大三角形失敗
[TestMethod]
public void ATest()
{
List<File> files = new List<File>();
for (int i = 0; i < 1; i++)
{
files.Add(new File(i + 1, 100));
}
const int maxSpeedInKbps = 1024; // 1MBps
Limiter limiter = new Limiter(maxSpeedInKbps);
DateTime startDateTime = DateTime.Now;
Parallel.ForEach(files, new ParallelOptions {MaxDegreeOfParallelism = 5}, file =>
{
DateTime currentFileStartTime = DateTime.Now;
Thread.Sleep(5);
limiter.Limit(currentFileStartTime, file.Blocks * Block.Size);
});
long roundOfWriteInKB = (files.Sum(i => i.Blocks.Count) * Block.Size)/1024;
int currentSpeedInKbps = (int) (roundOfWriteInKB/DateTime.Now.Subtract(startDateTime).TotalMilliseconds*1000);
Assert.AreEqual(maxSpeedInKbps, currentSpeedInKbps, string.Format("maxSpeedInKbps {0} currentSpeedInKbps {1}", maxSpeedInKbps, currentSpeedInKbps));
}
究竟你「遠」是什麼意思?你說多遠? –
你確定'Thread.Sleep'能阻止進一步的數據進入通道嗎?雖然這是事實,但你不會得到很多精確度,我不相信這是你的問題。你多久打一次'限制'? – jerry
如果您正在睡眠時間較短,那麼實際的睡眠時間將不準確 - 線程時間片爲15毫秒,因此對於最小三角洲來說,其雙倍或三倍值可提供合理的準確度。但是,您可以使用秒錶來衡量您睡眠的實際時間:http://msdn.microsoft.com/en-us/library/system.diagnostics.stopwatch.aspx –