Закройте метод, если его выполняет другой поток

У меня есть метод в многопоточном приложении, и я хотел бы следующее поведение при вызове этого метода:

  1. если никакие другие потоки в настоящее время не выполняют метод, выполните его.
  2. если другой поток в настоящее время выполняет метод, то выйдите из метода без его выполнения.

на lock оператор в C# полезен для ожидания завершения выполнения потока, но я не хочу сериализовать доступ к этому методу но скорее обходите выполнение этого метода, если он выполняется другим потоком.

4 ответов


вы можете сделать это с помощью монитора.TryEnter, но, возможно, проще: Interlocked:

int executing; // make this static if you want this one-caller-only to
               // all objects instead of a single object
void Foo() {
    bool won = false;
    try {
        won = Interlocked.CompareExchange(ref executing, 1, 0) == 0;
        if(won) {
           // your code here
        }
    } finally {
        if(won) Interlocked.Exchange(ref executing, 0);
    }

}

создайте переменную bool где-нибудь еще, установите true при запуске метода и false при выходе из метода, перед запуском метода проверьте, является ли переменная false, а затем запустите другой выход из метода


вот вспомогательный метод для этой цели:

static class Throttle
{
    public static void RunExclusive(ref int isRunning, Action action)
    {
        if (isRunning > 0) return;

        bool locked = false;
        try
        {
            try { }
            finally
            {
                locked = Interlocked.CompareExchange(ref isRunning, 1, 0) == 0;
            }

            if (locked) action();
        }
        finally 
        { 
            if (locked) 
                Interlocked.Exchange(ref isRunning, 0); 
        }
    }
}

и использовать его как:

private int _isTuning = 0;
private void Tune() { ... }

...

Throttle.RunExclusive(ref _isTuning, Tune);