我需要strategy.AllTablesUpdated();
在 2 毫秒内执行 50 个策略(我需要每秒重复约 500 次)。使用下面的代码,我发现仅Monitor.TryEnter
调用最多花费1 毫秒(!!!),我这样做了 50 次!
// must be called ~500 times per second
public void FinishUpdatingTables()
{
foreach (Strategy strategy in strategies) // about ~50, should be executed in 2 ms
{
// this slow and can be paralleled
strategy.AllTablesUpdated();
}
}
.....................
public override bool AllTablesUpdated(Stopwatch sw)
{
this.sw = sw;
Checkpoint(this + " TryEnter attempt ");
if (Monitor.TryEnter(desiredOrdersBuy))
{
Checkpoint(this + " TryEnter success ");
try
{
OnAllTablesUpdated();
} finally
{
Monitor.Exit(desiredOrdersBuy);
}
return true;
} else
{
Checkpoint(this + " TryEnter failed ");
}
return false;
}
public void Checkpoint(string message)
{
if (sw == null)
{
return;
}
long time = sw.ElapsedTicks / (Stopwatch.Frequency / (1000L * 1000L));
Log.Push(LogItemType.Debug, message + time);
}
从日志中(以 µs 为单位),失败的尝试花费了大约 1 毫秒:
12:55:43:778 调试:TryEnter 尝试 1264 12:55:43:779 调试:TryEnter 失败 2123
从日志(以 µs 为单位),成功尝试花费了 ~ 0.01ms:
12:55:49:701 调试:TryEnter 尝试 889 12:55:49:701 调试:TryEnter 成功 900
所以现在我认为这Monitor.TryEnter
对我来说太昂贵了,不能一个一个地执行 50 个策略。所以我想用Task
这样的方式并行这项工作:
// must be called ~500 times per second
public void FinishUpdatingTables()
{
foreach (Strategy strategy in strategies) // about ~50, should be executed in 2 ms
{
// this slow and can be paralleled
Task.Factory.StartNew(() => {
strategy.AllTablesUpdated();
});
}
}
我也可能会替换Monitor.TryEnter
为,lock
就像使用这种方法一样,一切都将是异步的。
我的问题:
- 为什么
Monitor.TryEnter
这么慢?(如果未获得锁定则为 1 ms) Task
每 2 毫秒启动 50 个任务 = 每秒 25 000 个任务会有多好?.NET 可以有效地管理这个吗?我还可以使用生产者-消费者模式BlockingCollection
并仅启动 50 个“工人”一次,然后每 2 毫秒向 BlockingCollection 提交 50 个项目的新包?那会更好吗?- 您将如何执行每 2 毫秒(每秒 500 次)可以并行执行的 50 个方法,总共每秒 25 000 次?