14

我在多线程应用程序中有一个方法,我希望在调用此方法时出现以下行为:

  1. 如果当前没有其他线程正在执行该方法,则执行它。
  2. 如果另一个线程当前正在执行该方法,则退出该方法而不执行它。

C# 中的lock语句对于等待线程完成执行很有用,但我不想序列化对此方法的访问,而是在另一个线程执行时绕过执行所述方法。

4

4 回答 4

13

您可以使用 Monitor.TryEnter 执行此操作,但可能更简单:互锁:

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);
    }

}
于 2012-09-13T18:14:06.047 回答
9

我想我不明白......如果一次只能由一个线程调用,为什么要多个线程调用它?

无论如何,您可以使用Monitor.TryEnter()false如果获取锁失败,它不会阻塞并返回。在这种情况下,您可以从函数中返回。

于 2012-09-13T18:09:19.473 回答
0

在其他地方创建布尔变量,在启动方法时设置为真,在方法退出时设置为假,在运行方法之前检查变量是否为假然后运行否则退出方法

于 2012-09-13T18:08:50.207 回答
0

这是一个用于此目的的辅助方法:

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);
于 2012-09-13T18:25:14.233 回答