如何一次限制一个方法调用?

时间:2009-02-09 17:47:08

标签: c# .net windows-services

我想知道如何实现以下限制:在早期调用完成之前,不应再次调用Windows服务中的一种方法。有问题的方法通过几个数据库表进行,非常重要的是在完成之前不会再次调用此过程。我有一个设置,定义我的服务将激活的频率,在正常情况下,它永远不会在早期调用完成之前激活(因为整个过程不应超过几分钟,间隔设置为10分钟)但不是果然。我想。

如何实现这个?

8 个答案:

答案 0 :(得分:12)

您可以使用named Mutexnamed Semaphor e来确保只有一个Mutex / Semaphore的持有者一次执行。正如评论者指出的那样,请记住,您必须小心不要放弃互斥锁或不正确地获取/释放信号量。

答案 1 :(得分:5)

一种方法是使用锁定:

private readonly object myLock = new object();

private void MyMethod()
{
   lock(myLock)
   {
      //code goes here
   }
}

这可确保此方法永远不会再运行一次。

答案 2 :(得分:2)

我是Mutex的第二个建议,但您可能还想看看交易。将整个代码包装在一个事务中(这需要using System.Transactions):

using(TransactionScope scope = new TransactionScope())
{
    try 
    {
        /* ... your current code here */
        scope.Complete();
    }
    catch (Exception e)
    {
        /* Any appropriate error handling/logging here */
    }
    finally
    {
    }
}

transactioncope会自动锁定所有相关表。您可以减少限制并允许其他进程读取,但不能写入您的进程正在触摸的数据。您可以通过将选项传递给TransactionsScope构造函数来完成此操作。

答案 3 :(得分:1)

如果所有代码都已本地化,您可以设置布尔值并在执行方法之前检查布尔值,否则您可以在执行之前IPC并请求状态。

答案 4 :(得分:1)

一些替代方案:

  1. 您可以在通话中检查以检查某些标志或调用Monitor.TryEnter并返回错误/如果否定则不执行任何操作。
  2. 您可以对调用进行排队(如果您需要此方法多次执行),并且仅在发出信号通知时调用。
  3. 如果你不介意阻塞,并且该方法在一个单独的线程上,你可以加入你想要等待的方法的线程。
  4. 我确定还有其他人。

答案 5 :(得分:0)

这听起来像是一个串行工作流......您是否考虑过使用工作流框架?

答案 6 :(得分:0)

如果您不介意一次将一个线程限制为整个对象,则可以使用:

Synchronization Contexts

  1. 让您的班级继承自 ContextBoundObject
  2. [同步] 属性应用于该课程。
  3. CLR一次只允许一个线程为每个类的实例执行代码。其他人将阻塞,直到当前线程释放锁定。

答案 7 :(得分:0)

如果您希望使用await / async

运行函数
private static readonly SemaphoreSlim yourLock = new SemaphoreSlim(1, 1); //allow only 1 thread at time

...
private async Task<string> YourFunction() { 
await yourLock.WaitAsync();
            try
            {
                //your code go here
            }
            finally
            {
                yourLock.Release();
            }
}