gpt4 book ai didi

c# - 多个资源的 Monitor.TryEnter

转载 作者:行者123 更新时间:2023-11-30 16:21:06 25 4
gpt4 key购买 nike

我尝试搜索此内容,但没有找到最适合我所面临问题的建议。

我的问题是我们有可用资源(计算引擎)的列表/堆栈。这些资源用于执行某些计算。

执行计算的请求是由外部进程触发的。所以当请求计算时,我需要检查是否有任何可用资源当前没有执行其他计算,如果是,请等待一段时间再检查。

我想知道实现它的最佳方法是什么。我有以下代码,但不确定它是否非常安全。

如果您有任何进一步的建议,那就太好了:

void Process(int retries = 0) {
CalcEngineConnection connection = null;
bool securedConnection = false;
foreach (var calcEngineConnection in _connections) {
securedConnection = Monitor.TryEnter(calcEngineConnection);
if (securedConnection) {
connection = calcEngineConnection;
break;
}
}
if (securedConnection) {
//Dequeue the next request
var calcEnginePool = _pendingPool.Dequeue();

//Perform the operation and exit.
connection.RunCalc(calcEnginePool);
Monitor.Exit(connection);
}
else {
if (retries < 10)
retries += 1;
Thread.Sleep(200);
Process(retries);
}
}

最佳答案

无论如何,我不确定使用 Monitor 是否是最好的方法,但是如果您确实决定走那条路,我会将上面的代码重构为:

bool TryProcessWithRetries(int retries) {
for (int attempt = 0; attempt < retries; attempt++) {
if (TryProcess()) {
return true;
}
Thread.Sleep(200);
}
// Throw an exception here instead?
return false;
}

bool TryProcess() {
foreach (var connection in _connections) {
if (TryProcess(connection)) {
return true;
}
}
return false;
}

bool TryProcess(CalcEngineConnection connection) {
if (!Monitor.TryEnter(connection)) {
return false;
}
try {
var calcEnginePool = _pendingPool.Dequeue();
connection.RunCalc(calcEnginePool);
} finally {
Monitor.Exit(connection);
}
return true;
}

这分解了三个逻辑:

  • 重试几次
  • 尝试集合中的每个连接
  • 尝试单一连接

它还为此避免使用递归,并将 Monitor.Exit 调用放入 finally block 中,绝对应该在。

您可以将中间方法实现替换为:

return _connections.Any(TryProcess);

...但这可能有点太“聪明”了。

就我个人而言,我很想将 TryProcess 移动到 CalcEngineConnection 本身 - 这样 this 代码就不需要知道是否或不是连接能够处理某些东西——这取决于对象本身。这意味着您可以避免拥有公开可见的锁,而且如果将来某些资源可以(比如说)一次处理两个请求,这将是灵活的。

关于c# - 多个资源的 Monitor.TryEnter,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/13499028/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com