Mik*_*urs 2 c# linq stack-overflow multithreading dictionary
我有以下字典:
Dictionary<long, ChangeLogProcess> _changeLogProcesses =
new Dictionary<long, ChangeLogProcess>();
Run Code Online (Sandbox Code Playgroud)
我有一个方法试图在特定状态的字典中获取下一个changelogprocess(如果没有特定状态的项,则返回null):
var changeLogProcesses =
from entry in _changeLogProcesses
where (entry.Value.Status == status)
select entry.Value;
changeLogProcess = changeLogProcesses.FirstOrDefault<ChangeLogProcess>();
Run Code Online (Sandbox Code Playgroud)
但是,在执行期间,它在linq查询期间抛出了堆栈溢出异常?我做了很多测试,以确保列表中有项目等等,但问题仍然存在?
值得注意的是,此方法是在多线程环境中运行的服务的一部分.上面的linq查询(以及对它的所有访问,例如添加/删除到列表中的项目,或列表中项目的状态更改)都包含在ReaderWriterLockSlim写锁中.同样,我已经对它进行了广泛的调试,以确保在任何时候都不会有单个线程访问列表.
什么可能导致它堆栈溢出,因为与一些可能的其他错误相关,例如在查询期间修改列表?(再次,我在任何时候只有一个线程访问列表)
编辑:根据要求获取getter和setter代码:
public ChangeLogProcessStatus Status
{
get { return _status; }
set
{
//more that one place can initiate a retry now, so retry count is handled in the property setter
if (PreviousStatus <= ChangeLogProcessStatus.Waiting && value >= ChangeLogProcessStatus.RetryWaiting)
{
this.ChangeLog.Tries++;
//If it's retry waiting, remove this last service machine from the
//list so it can try it again because it's not an error
if (value == ChangeLogProcessStatus.RetryWaiting && _previousServiceMachineIds.Count > 0)
{
_previousServiceMachineIds.RemoveAt(_previousServiceMachineIds.Count() - 1);
}
}
PreviousStatus = _status;
_status = value;
}
}
Run Code Online (Sandbox Code Playgroud)
最后编辑 - 我删除了前面的示例,因为该代码中不存在该问题.
事实证明它是在应用程序的不同部分,并且很难找到一个递归.巧合的是,在linq查询期间引发了堆栈溢出错误,因此被递归地调用了420000+次.
下面的所有答案都是有用的,并且是在多线程应用程序中找到问题的正确途径,但是第一个答案肯定强调递归作为问题,结果是它(尽管它不是属性访问者之一似乎很明显).
再次感谢
谢谢
检查ChangeLogProcess类的属性以确保它不是自引用的.我认为,在这种情况下,这是导致堆栈溢出异常的最可能原因.
例如:
private ChangeLogStatus status;
public ChangeLogStatus Status
{
get { return this.Status; } // instead of this.status
set { this.status = value }
}
Run Code Online (Sandbox Code Playgroud)
另一种可能的替代方案是在状态的相等性检查中.你有没有为ChangeLogStatus重写Equals()?检查那里以确保您没有任何自引用代码(或至少一种终止递归的方式).