Правильно распоряжаться классом с резьбой - PullRequest
4 голосов
/ 22 сентября 2009

У меня работает довольно сложная многопоточная служба Windows, но я не могу понять, как правильно ее очистить. Ниже приведен некоторый [псевдо] код, чтобы показать, что у меня есть. Фактический код намного сложнее, возможно, его слишком много, чтобы скопировать / вставить здесь.

По сути, у меня есть класс Request, который создает поток для выполнения работы. Когда новый запрос поступает в прослушиватель, он отправляет его процессору, который создает новый запрос и поддерживает список запросов. Если служба остановлена, я очищаю все запросы в списке. Но когда работа с Запросом завершена, как мне очистить этот экземпляр класса?

Спасибо за любую помощь!

Nelson

class Service
{
  Listener listener;
  Processor processor;

  OnStart()
  {
    processor = new Processor();
    listener = new Listener(processor);
  }

  OnStop()
  {
    listener.Dispose();
    processor.Dispose();
  }
}

class Listener
{
  Thread thread;
  bool terminate = false;

  Listener(Processor processor)
  {
    thread = new Thread(DoWork);
    thread.Start(processor);
  }

  DoWork(Processor processor)
  {
    WaitForConnection(NewConnection);
  }

 NewConnection(String data)
 {
    processor.NewRequest(data);

    if (terminate)
      return;

   WaitForConnection(NewConnection);
 }

  Dispose()
  {
    terminate = true;
    thread.Join();
  }
}

class Processor
{
  //I need to maintain this list so that when the service stops I can cleanly close down
  List<Request> requests = new List<Request>();

  NewRequest(string data)
  {
    request.Add(new Request(data));
  }

  Dispose()
  {
    //Cleanup each request
    foreach (Request request in requests)
    {
      request.Dispose();
    }
  }
}

class Request
{
  Thread thread;
  bool terminate;

  Request(string data)
  {
    while (true)
    {
      //Do some work
      Thread.Sleep(1000);

      if (doneWorking)
        break;

      if (terminate)
        return;
    }

    //We're done.  If I return this thread stops.  But how do I properly remove this Request instance from the Processor.requests list?
  }

  Dispose()
  {
    terminate = true;
    thread.Join();
  }
}

Ответы [ 2 ]

4 голосов
/ 22 сентября 2009

Одна из возможностей - передать ответный запрос на запрос в форме делегата: «Когда вы закончите обработку, перезвоните мне, чтобы сказать мне». Затем просто выполните обратный вызов в конце обработки запроса и дайте ему выполнить очистку.

Однако следует остерегаться одной вещи: если вы попытаетесь просмотреть свой список, выбрасывая вещи, а затем попытаетесь удалить элемент из списка в другой ветке, у вас возникнут проблемы. Вам, вероятно, следует сохранить флаг (доступ к которому осуществляется потокобезопасным способом), и, как только вы начнете избавляться от всего в списке, игнорируйте все обратные вызовы, которые вы получите.

3 голосов
/ 23 сентября 2009

Это грубый набросок:

delegate void CompletedRequest(Request req);

class Processor : ITrackCompletion
{
    //I need to maintain this list so that when the service stops I can cleanly close down
    List<Request> requests = new List<Request>();

    public void NewRequest(string data)
    {
        lock(requests)
            request.Add(new Request(data), Complete);
    }

    public void Complete(Request req)
    {
        lock (requests)
            requests.Remove(req);
    }

    public void Dispose()
    {
        //Cleanup each request
        foreach (Request request in requests.ToArray())
        {
            request.Dispose();
        }
    }
}

class Request
{
    Thread thread;
    bool terminate;

    public Request(string data, CompletedRequest complete)
    {
        try
        {
            while (true)
            {
                //Do some work
                Thread.Sleep(1000);

                if (doneWorking)
                    break;

                if (terminate)
                    return;
            }
        }
        finally
        {
            //We're done.  If I return this thread stops.  But how do I properly remove this Request instance from the Processor.requests list?
            complete(this);
        }
    }

    void Dispose()
    {
        terminate = true;
        thread.Join();
    }
}
...