检测死锁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,如果你们有一个更好的/好的主意,并询问你的意见。

谢谢你的帮助=)

检测死锁WinForms应用程序

由于现有的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)
    {
        // ...
    }
}