Как ограничиться одним вызовом метода за раз? - PullRequest
5 голосов
/ 09 февраля 2009

Я хотел бы знать, как реализовать следующее ограничение: Один метод в моей службе Windows не должен вызываться повторно до завершения предыдущего вызова. Рассматриваемый метод проходит через пару таблиц базы данных, и очень важно, чтобы этот процесс больше не вызывался до его завершения. У меня есть параметр, который определяет, как часто моя служба будет активироваться, и при нормальных обстоятельствах она никогда не активируется до завершения предыдущего вызова (потому что весь процесс не должен занимать более пары минут, а интервал устанавливается равным 10 минутам), но это не так. конечно же Я думаю.

Как это реализовать?

Ответы [ 8 ]

12 голосов
/ 09 февраля 2009

Вы можете использовать с именем Mutex или с именем Semaphor e, чтобы гарантировать, что только один держатель Mutex / Семафор исполняет одновременно. Как отметил комментатор, имейте в виду, что вы должны быть осторожны, чтобы не отказаться от мьютекса или неправильно приобрести / освободить семафор.

5 голосов
/ 09 февраля 2009

Одним из способов будет использование блокировки:

private readonly object myLock = new object();

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

Это гарантирует, что этот метод никогда не сможет запускаться более одного раза за раз.

2 голосов
/ 09 февраля 2009

Я второе предложение 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
    {
    }
}

Транзакция автоматически блокирует все связанные таблицы. Вы можете уменьшить ограничения и разрешить другим процессам читать, но не записывать данные, к которым относится ваш процесс. Это можно сделать, передав параметры конструктору TransactionsScope.

1 голос
/ 09 февраля 2009

Некоторые альтернативы:

  1. Вы можете поставить галочку в вызове, чтобы проверить какой-либо флаг или вызвать Monitor.TryEnter и вернуться с ошибкой / ничего не делать, если отрицательный.
  2. Вы можете ставить в очередь вызовы (если вам нужно, чтобы этот метод выполнялся более одного раза), и вызывать только тогда, когда монитор получил сигнал.
  3. Если вы не возражаете против блокировки, а метод находится в отдельном потоке, вы можете присоединиться к потоку метода, который вы хотите подождать.

Я уверен, что есть другие.

1 голос
/ 09 февраля 2009

Хорошо, если весь код локализован, вы можете установить логическое значение и проверить логическое значение перед выполнением метода, в противном случае вы можете выполнить IPC и запросить состояние перед выполнением.

0 голосов
/ 26 апреля 2018

Если вы хотите, чтобы ваша функция работала с 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();
            }
}
0 голосов
/ 09 февраля 2009

Если вы не возражаете ограничивать один поток за раз всем объектом, тогда вы можете использовать:

Контексты синхронизации

  1. Ваш класс наследуется от ContextBoundObject
  2. Применение атрибута [Синхронизация] к классу.

CLR будет позволять только одному потоку одновременно выполнять код для экземпляра этого класса. Остальные будут блокироваться, пока текущий поток не снимет блокировку.

0 голосов
/ 09 февраля 2009

Звучит как последовательный рабочий процесс ... Рассматривали ли вы использование фреймворка рабочего процесса?

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...