Временный сбой службы Windows из-за нескольких запущенных потоков - PullRequest
0 голосов
/ 02 июля 2010

Я работаю над простым веб-сервисом, который экспортирует данные из некоторого хранилища данных в базу данных.

Служба запускается каждые 20 секунд (интервал тестирования).

Интервалы реализуются черезSystem.Timers.Timer класс.

На данный момент происходит:

  1. Служба запускается
  2. Таймер запускается
  3. Проходит 20 секунд и служба запускаетсяэкспорт
  4. Экспорт не завершается в течение следующих 20 секунд, и другой поток начинает попытки сделать такой же экспорт.
  5. В конечном итоге происходит сбой службы.

Я собирался обернуть экспорт в отдельный поток, но не уверен, полностью ли это решит проблему.

Увеличение интервала времени не вариант, потому что я не уверен, насколько большим будет будущий экспорт.

Любые предложения приветствуются.

Спасибо

Редактировать:

Я предполагаю, что мне нужно: 1. Запустить таймер 2. Запустить поток 3. Начать экспорт 4. Не позволяйте таймеру запустить другой потокпока предыдущий не завершится ...

Ответы [ 3 ]

4 голосов
/ 02 июля 2010

Как на шаге 3 вы сначала отключаете таймер, затем, когда вы закончите с экспортом, вы снова активируете таймер?

3 голосов
/ 02 июля 2010

Я бы сделал что-то подобное.

public class MyServiceController
{
  private Thread m_Thread = new Thread(() => { Run(); });
  private ManualResetEvent m_StopSignal = new ManualResetEvent();

  public void Start()
  {
    m_Thread.Start();
  }

  public void Stop()
  {
    m_StopSignal.Set(); // Give it chance to end on its own.
    if (!m_Thread.Join(TimeSpan.FromSeconds(30))
    {
      // Tear everything down forcefully as an absolute last resort.
      m_Thread.Abort();
    }
  }

  private void Run()
  {
    while (!m_StopSignal(TimeSpan.FromSeconds(20))
    {
      // Put your code here.
    }
  }
}

При таком подходе выделяется один выделенный поток для обработки, который поддерживает все синхронно. Обратите внимание, что он использует WaitHandle для регулирования интервалов. Также важно отметить, что я пропустил много кода, который сделал бы MyServiceController более устойчивым, как, например, работа с вызывающими абонентами, которые хотят вызывать Start несколько раз, убедившись, что рабочий поток завершается, если он не хочет останавливаться мирно и т. д.

1 голос
/ 02 июля 2010

Иногда вы не хотите останавливать свой таймер, потому что он может порождать несколько потоков.В этом случае вы оборачиваете критические части каждого потока в блок Monitor.TryEnter, блокируя общий объект, так что если поток все еще работает, когда таймер снова запускается, новый поток безболезненно проваливается.

private static object lockObject = new object();
public void DoSomething()
{
    if (System.Threading.Monitor.TryEnter(lockObject))
    {
        try
        {
            // critical stuff 
        }
        finally
        {
            System.Threading.Monitor.Exit(lockObject);
        }
    }
}
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...