Identify the thread which holds the lock

后端 未结 6 1056
佛祖请我去吃肉
佛祖请我去吃肉 2020-12-25 11:03

one of the threads in my application blocked at the following lock statement and resulted in a deadlock

void ExecuteCommand()
{
    lock(this._lockinstance)
         


        
6条回答
  •  夕颜
    夕颜 (楼主)
    2020-12-25 11:10

    You can implement a Monitor wrapper that saves stack traces & thread names on enter.

    Old way:

    private object myLock = new object();
    
    ...
    lock(myLock)
    {
        DoSomething();
    }
    ...
    

    With code below:

    private SmartLock myLock = new SmartLock();
    
    ...
    myLock.Lock( () =>
    {
        DoSomething();
    }
    );
    ...
    

    Source:

    public class SmartLock
    {
        private object LockObject = new object();
        private string HoldingTrace = "";
    
        private static int WARN_TIMEOUT_MS = 5000; //5 secs
    
    
        public void Lock(Action action)
        {
            try
            {
                Enter();
                action.Invoke();
            }
            catch (Exception ex)
            {
                Globals.Error("SmartLock Lock action", ex);
            }
            finally
            {
                Exit();
            }
    
        }
    
        private void Enter()
        {
            try
            {
                bool locked = false;
                int timeoutMS = 0;
                while (!locked)
                {
                    //keep trying to get the lock, and warn if not accessible after timeout
                    locked = Monitor.TryEnter(LockObject, WARN_TIMEOUT_MS);
                    if (!locked)
                    {
                        timeoutMS += WARN_TIMEOUT_MS;
                        Globals.Warn("Lock held: " + (timeoutMS / 1000) + " secs by " + HoldingTrace + " requested by " + GetStackTrace());
                    }
                }
    
                //save a stack trace for the code that is holding the lock
                HoldingTrace = GetStackTrace();
            }
            catch (Exception ex)
            {
                Globals.Error("SmartLock Enter", ex);
            }
        }
    
        private string GetStackTrace()
        {
            StackTrace trace = new StackTrace();
            string threadID = Thread.CurrentThread.Name ?? "";
            return "[" + threadID + "]" + trace.ToString().Replace('\n', '|').Replace("\r", "");
        }
    
        private void Exit()
        {
            try
            {
                Monitor.Exit(LockObject);
                HoldingTrace = "";
            }
            catch (Exception ex)
            {
                Globals.Error("SmartLock Exit", ex);
            }
        }
    }
    

提交回复
热议问题