检测死锁WinForms应用程序
本文关键字:应用程序 WinForms 死锁 检测 | 更新日期: 2023-09-27 18:17:25
我们有一个相当大的winforms桌面应用程序。我们的应用程序每隔一段时间就会出现死锁,我们不确定这是怎么发生的。
我们知道这是由锁定操作引起的。所以我们有很多像这样的代码部分:
lock (_someObj)
DoThreadSaveOperation();
为了能够检测死锁是由什么引起的,我们想把所有的锁操作转换成这样的形式:
bool lockTaken = false;
var temp = _someObj;
try {
System.Threading.Monitor.TryEnter(temp, 1000, ref lockTaken);
if (!lockTaken)
{
// log "can't get lock, maybe deadlock, print stacktrace
}
DoThreadSaveOperation();
}
finally {
System.Threading.Monitor.Exit(temp);
}
这个"锁服务"应该放在中心位置。问题是,它必须像这样调用:
LockService.RunWithLock(object objToLock, Action methodToRun);
这意味着我们必须为每个锁后执行的语句创建一个委托函数。
由于这将是一个很大的重构,我想我应该尝试一下stackoverflow,如果你们有一个更好的/好的主意,并询问你的意见。
谢谢你的帮助=)
由于现有的lock
功能紧密地模拟了using
语句,我建议您将逻辑包装在实现IDisposable的类中。
类的构造函数将尝试获取锁,如果它无法获得锁,您可以抛出异常或记录它。Dispose()方法将释放锁。
您将在using
语句中使用它,因此它在面对异常时将是健壮的。
所以像这样:
public sealed class Locker: IDisposable
{
readonly object _lockObject;
readonly bool _wasLockAcquired;
public Locker(object lockObject, TimeSpan timeout)
{
_lockObject = lockObject;
Monitor.TryEnter(_lockObject, timeout, ref _wasLockAcquired);
// Throw if lock wasn't acquired?
}
public bool WasLockAquired
{
get
{
return _wasLockAcquired;
}
}
public void Dispose()
{
if (_wasLockAcquired)
Monitor.Exit(_lockObject);
}
}
你可以这样使用:
using (var locker = new Locker(someObj, TimeSpan.FromSeconds(1)))
{
if (locker.WasLockAquired)
{
// ...
}
}