【问题标题】:LockRecursionException in multiple threaded function多线程函数中的 LockRecursionException
【发布时间】:2021-08-06 03:11:50
【问题描述】:

我不知道如何描述它,但是当代码写得很好时,我得到了一个例外。此异常与 ReaderWriterLockSlim 有关,它是 LockRecursionException;它出现在“ScreenLocker.EnterReadLock();”线。找不到我的代码和描述在互联网上做什么或可能有问题的问题,这就是为什么我在这里写这个问题并向大家寻求帮助。这是我有问题的代码:

public static List<Dictionary<int, int>> RunTasks(ScreenScanning ss)
    {
        var listOfTasks = new List<Task>();
        List<Dictionary<int, int>> PosXOfBlocksAndMeaningOfIt = new List<Dictionary<int, int>>();
        for (var i = 0; i <= BlocksOnYAxisOnScreen; i++)
        {
            ScreenLocker.EnterReadLock();
            var t = new Task(() =>
            {
                PosXOfBlocksAndMeaningOfIt.Add(ss.XAxysScan(PosYOfRowsToScan[i], Screen, ref ScreenLocker));
            });
            listOfTasks.Add(t);
        }
        Task.WaitAll(listOfTasks.ToArray());
        return PosXOfBlocksAndMeaningOfIt;
    }

这些是这个方法调用的函数:

public Dictionary<int, int> XAxysScan(int posY, Bitmap screen, ref ReaderWriterLockSlim screenLocker)
    {
        screenLocker.ExitReadLock();
        Dictionary<int, int> partOfMainTable = new Dictionary<int, int>();
        partOfMainTable.Add(666, posY); //used in BotViewUpdate in DataToTableInterpreter
        for (int i = 0; i <= 1920; i++)
        {
            if (screen.GetPixel(i, posY) == ColorsInRow[0])
            {
                if (IsFarmable(posY, ColorsInRow, i, screen))
                {
                    partOfMainTable.Add(i, 1);
                }
            }
            else if (IsBackground(BackgroundColors, i, posY, screen))
            {
                partOfMainTable.Add(i, 0);
            }
            else
            {
                partOfMainTable.Add(i, 2);                
            }
        }
        return partOfMainTable;
    }

你怎么能看到我在进入 XAxysScan 函数后立即释放了锁。

【问题讨论】:

    标签: c# multithreading exception readerwriterlockslim readerwriterlock


    【解决方案1】:

    你怎么能看到我在进入 XAxysScan 函数后立即释放了锁。

    ReaderWriterLockSlim 是一个synchronization object,它允许多个线程从一个资源中读取,但只允许一个资源写入它(理想情况下)。

    之所以重要,是因为ReaderWriterLockSlim实现这个效果的具体方式,需要一个叫Managed Thread Affinity的东西,这基本上意味着无论Task或者叫EnterReadLock()的Thread都必须是相同 Task 或调用ExitReadLock(); 的线程。

    当我们查看以下内容时,我们可以看到你有 RunTasks(ScreenScanning ss) 进入锁,但你立即开始一个新的孩子 Task 并将 ReaderWriterLockSlim 作为引用传递给 XAxysScan()。

    ScreenLocker.EnterReadLock();
    var t = new Task(() =>
    {
        PosXOfBlocksAndMeaningOfIt.Add(ss.XAxysScan(PosYOfRowsToScan[i], Screen, ref ScreenLocker));
    });
    

    只有进入锁的同一个Task 才能释放该锁。至少对于像ReaderWriterLockSlim 这样使用Managed Thread Affinity 的同步对象。

    考虑将EnterReadLock() 移动到XAxysScan() 方法中。

    public Dictionary<int, int> XAxysScan(int posY, Bitmap screen, ref ReaderWriterLockSlim screenLocker)
    {
        screenLocker.EnterReadLock();
        try{
            Dictionary<int, int> partOfMainTable = new Dictionary<int, int>();
        partOfMainTable.Add(666, posY); //used in BotViewUpdate in DataToTableInterpreter
            for (int i = 0; i <= 1920; i++)
            {
                if (screen.GetPixel(i, posY) == ColorsInRow[0])
                {
                    if (IsFarmable(posY, ColorsInRow, i, screen))
                    {
                        partOfMainTable.Add(i, 1);
                    }
                }
                else if (IsBackground(BackgroundColors, i, posY, screen))
                {
                    partOfMainTable.Add(i, 0);
                }
                else
                {
                    partOfMainTable.Add(i, 2);                
                }
            }
            return partOfMainTable;
        }
        finally
        {
            // make sure that even if we encounter an error, we still exit the lock so other threads can enter the lock / begin writing
            screenLocker.ExitReadLock();
        }
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2015-06-11
      • 2016-05-15
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多