简体   繁体   中英

How to restrict to one method call at a time?

I'd like to know how to implement the following restriction: One method in my Windows Service should not be called again before the earlier call has been finished. The method in question goes thru couple of database tables and it's very important that this process won't be called again before it's finished. I have a setting that defines how often my service will activate and under normal circumstances it never activates before the earlier call has been finished (because whole process should not take more than couple of minutes and the interval is set to 10 minutes) but thats not sure enough. I guess.

How to implement this?

You can use a named Mutex or a named Semaphor e to ensure that only one holder of the Mutex/Semaphore is executing at once. As a commenter pointed out, keep in mind you must be careful not to abandon a mutex or improperly acquire/release a semaphore.

One way would be to use locking:

private readonly object myLock = new object();

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

This ensures that this method can never be running more that once at a time.

I second the Mutex suggestion, but you might also want to take a look at transactions. Wrap your entire code in a transaction (this requires a 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
    {
    }
}

A transactionscope automatically locks all related tables. You can reduce the restrictions and allow other processes to read, but not write to the data that your process is touching. You do this by passing options to the TransactionsScope constructor.

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

Some alternatives:

  1. You can put a check in the call to check some flag or call Monitor.TryEnter and return with an error/do nothing if negative.
  2. You can queue up calls (if you need this method to execute more than once) and only invoke when Monitor has been signaled.
  3. If you don't mind blocking, and the method is on a separate thread, you can join the thread of the method you want to wait.

I'm sure there are others.

If you want your function run with 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();
            }
}

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

If you don't mind restricting one thread at a time to the entire object, then you can use:

Synchronization Contexts

  1. Have your class inherit from ContextBoundObject
  2. Apply a [Synchronization] attribute to the class.

The CLR will only allow one thread at a time to execute code per instance of this class. The others will block until the lock is released by the current thread.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM