简体   繁体   English

检测死锁WinForms应用程序

[英]Detecting deadlocks WinForms application

we have a quite large winforms desktop application. 我们有一个很大的winforms桌面应用程序。 Our application runs every once in a while into a deadlock and we are not sure how this happens. 我们的应用程序偶尔会陷入僵局,我们不确定这是怎么发生的。

We do know that this is caused by a locking operation. 我们确实知道这是由锁定操作引起的。 So we have quite a lot code parts like this: 因此,我们有很多这样的代码部分:

lock (_someObj)
  DoThreadSaveOperation();

Our approach to be able to detect what the deadlock was caused by we want to convert all those lock operations into something like this: 我们能够检测到死锁是由我们想要将所有这些锁操作转换为如下所示的方法:

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);   
}  

This "lock service" should be at a central position. 此“锁定服务”应处于中心位置。 The problem is that it then has to be called like this: 问题在于它必须像这样被调用:

  LockService.RunWithLock(object objToLock, Action methodToRun);

That would mean that we had to create a delegate function for each statement which is executed after a lock. 这意味着我们必须为锁后执行的每个语句创建一个委托函数。

Since this would be a lot of refactoring, I thought I'd give a try on stackoverflow if you guys have a better/good idea about this and also ask for your opinion. 由于这将需要大量重构,所以我想如果你们对此有更好/更好的主意并且也征求您的意见,我想尝试一下stackoverflow。

Thanks for you help =) 谢谢您的帮助=)

Since the existing lock functionality closely models a using statement, I suggest that you wrap up your logic in a class that implements IDisposable. 由于现有的lock功能紧密地模拟了using语句,因此建议您将逻辑包装在实现IDisposable的类中。

The class's constructor would attempt to get the lock, and if it failed to get the lock you could either throw an exception or log it. 该类的构造函数将尝试获取该锁,如果无法获取该锁,则可以引发异常或将其记录下来。 The Dispose() method would release the lock. Dispose()方法将释放锁定。

You would use it in a using statement so it will be robust in the face of exceptions. 您可以在using语句中使用它,因此在遇到异常时它将很健壮。

So something like this: 所以像这样:

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);
    }
}

Which you could use like this: 您可以这样使用:

using (var locker = new Locker(someObj, TimeSpan.FromSeconds(1)))
{
    if (locker.WasLockAquired)
    {
        // ...
    }
}

Which I think will help to minimise your code changes. 我认为这将有助于最大程度地减少代码更改。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM