Я могу добавить атрибут к функции для предотвращения возвращения?

@nileshkumar был прав в том, что ошибка была обнаружена в моей модели проекта. Код в моем приложении был написан как метка инструмента, тогда как модель была создана как метка инструмента.

7
задан Constantin 24 November 2008 в 16:12
поделиться

7 ответов

Вместо того, чтобы использовать bool и установить его непосредственно, попытайтесь использовать длинное и Взаимно блокируемый класс:

long m_InFunction=0;

if(Interlocked.CompareExchange(ref m_InFunction,1,0)==0)
{
  // We're not in the function
  try
  {
  }
  finally
  {
    m_InFunction=0;
  }
}
else
{
  // We're already in the function
}

Это осуществит ориентированную на многопотоковое исполнение проверку.

16
ответ дан 6 December 2019 в 06:15
поделиться

Без блока и перезаписи IL, нет никакого способа для Вас создать пользовательский атрибут, который изменяет код в способе, которым Вы описываете.

Я предлагаю, чтобы Вы использовали основанный на делегате подход вместо этого, например, для функций отдельного аргумента:

static Func<TArg,T> WrapAgainstReentry<TArg,T>(Func<TArg,T> code, Func<TArg,T> onReentry)
{
    bool entered = false;
    return x =>
    {
        if (entered)
            return onReentry(x);
        entered = true;
        try
        {
            return code(x);
        }
        finally
        {
            entered = false;
        }
    };
}

Этот метод берет функцию для обертывания (предположение, что это соответствует Func <TArg, T> - можно записать другие варианты или полностью универсальную версию с большим усилием), и альтернативная функция для вызова в случаи возвращения. (Альтернативная функция могла выдать исключение или сразу возвратиться, и т.д.) Затем всюду по Вашему коду, где Вы будете обычно называть переданный метод, Вы называете делегата возвращенным WrapAgainstReentry () вместо этого.

5
ответ дан 6 December 2019 в 06:15
поделиться

Вы могли создать атрибут PostSharp для проверки, чтобы видеть, находится ли название метода в текущем отслеживании стека

    [MethodImpl(MethodImplOptions.NoInlining)]
    private static bool IsReEntry() {
        StackTrace stack = new StackTrace();
        StackFrame[] frames = stack.GetFrames();

        if (frames.Length < 2)
            return false;

        string currentMethod = frames[1].GetMethod().Name;

        for (int i = 2; i < frames.Length; i++) {
            if (frames[i].GetMethod().Name == currentMethod) {
                return true;
            }
        }

        return false;
    }
4
ответ дан 6 December 2019 в 06:15
поделиться

Можно найти, что Вы могли использовать PostSharp для выполнения этого - наряду с предложениями от Anthony об использовании попытки/наконец. Это, вероятно, будет грязно все же. Также рассмотрите, хотите ли Вы, чтобы повторная входимость была на основе на экземпляр или на поток. (Несколько потоков могли звонить в метод для начала, или нет?)

Нет ничего как это в самой платформе.

2
ответ дан 6 December 2019 в 06:15
поделиться

Нет такого предопределенного атрибута. Можно сделать новые атрибуты, но это не поможет Вам. Проблема заставляет пользовательский атрибут предотвратить метод, называемый снова, который я не думаю, является выполнимым.

Оператор блокировки не то, что Вы хотите, так как это заставит вызовы блокироваться и ожидать, не сразу возвращаются.

PS: используйте попытку... наконец блок в вышеупомянутом образце. Иначе, если исключение будет выдано посреди функции, то inFunction1 оставят верным, и все вызовы сразу возвратятся.

например:

if (inFunction1) 
   return;

try
{
  inFunction1 = true;

  // do stuff which might cause function1 to get called
  ...
}
finally 
{
  inFunction1 = false;
}
1
ответ дан 6 December 2019 в 06:15
поделиться

Я не думаю, что это будет возможно.

Самым близким будет 'Синхронизируемый' атрибут, но это заблокирует все последующие вызовы.

0
ответ дан 6 December 2019 в 06:15
поделиться

Если это для Потокобезопасности, необходимо быть осторожными с той переменной.

Возможно, что другой поток мог войти в функцию и пройти проверку, прежде чем первый поток установил переменную.

Удостоверьтесь, что это отметило энергозависимый как так:

private volatile bool inFunction1 = false;
1
ответ дан 6 December 2019 в 06:15
поделиться
Другие вопросы по тегам:

Похожие вопросы: