Блокировка рекурсии (т. Е. Блокировка, работающая в том же потоке) - PullRequest
0 голосов
/ 05 июня 2018

Я хотел бы иметь блокировку, которая предотвращает ввод части кода из потока того же , чтобы сделать его более пуленепробиваемым от бесконечной рекурсии.То есть что-то вроде:

private static object RecurseLock = new object();
public void PartiallyRecursiveMethod()
{
    if (TryEnter(RecurseLock))
    {
        try
        {
            Console.WriteLine("Hello ");
            // we want to do it again now
            PartiallyRecursiveMethod();
        }
        finally
        {
            Release(RecurseLock);
        }
    }
    Console.WriteLine("world!");
}

Так, что результат вызова PartiallyRecursiveMethod будет " Hello world! ".(или, может быть, там есть новая строка, я забыл, как работает Console.WriteLine)

TryEnter должен применяться только к потоку current .Другие темы не должны быть заблокированы.

Есть ли в C # что-то, что уже делает это, или я должен написать свой собственный?Я полагаю, что все обычные подозреваемые (Monitor.TryEnter, SemaphoreSlim и т. Д.) Получают только блокировку, исключающую различные потоки;использование их здесь просто вызовет переполнение стека.

Это должно быть в .NET 2.

Кстати, я знаю, что это требование указывает на то, что код очень плохой ичто на самом деле переписать код будет более разумным.Тем не менее мне интересно, предлагает ли .NET что-то подобное.

1 Ответ

0 голосов
/ 05 июня 2018

Как отмечали несколько человек, в .Net 2.x вы можете использовать [ThreadStatic] для этого:

using System;
using System.Threading;
using System.Threading.Tasks;

namespace Demo
{
    class Program
    {
        static void Main()
        {
            Parallel.Invoke(test, test, test);
        }

        static void test()
        {
            if (_thisThreadAlreadyHere)
            {
                Console.WriteLine($"Thread {Thread.CurrentThread.ManagedThreadId} is already working.");
                return;
            }

            _thisThreadAlreadyHere = true;

            try
            {
                Console.WriteLine($"Thread {Thread.CurrentThread.ManagedThreadId} is working.");

                Thread.Sleep(1000);
                test();
                Thread.Sleep(1000);

                Console.WriteLine($"Thread {Thread.CurrentThread.ManagedThreadId} has completed.");
            }

            finally
            {
                _thisThreadAlreadyHere = false;
            }
        }

        [ThreadStatic]
        static bool _thisThreadAlreadyHere;
    }
}

Однако я бы сказал, что попытка решить проблемы "бесконечной рекурсии" в этомпуть несколько подозрительный.Я бы подумал, что должен быть лучший способ исправить логику - это похоже на гипсовый подход.

...