正确处理带线程的类

时间:2009-09-22 19:05:02

标签: c# class multithreading dispose

我有一个相当复杂的多线程Windows服务,但我无法弄清楚如何正确清理。下面是一些显示我拥有的[伪]代码。实际代码要复杂得多,复制/粘贴可能太多了。

基本上,我有一个类Request创建一个线程来完成工作。当一个新请求进入监听器时,它会将它发送到处理器,处理器创建新的请求并维护请求列表。如果服务停止,我清理列表中的所有请求。但是当Request工作完成后,我该如何清理该类的一个实例?

感谢您的帮助!

纳尔逊

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 个答案:

答案 0 :(得分:4)

一种可能性是以委托的形式将回调传递给请求:“当你完成处理后,给我回电话告诉我”。然后在请求处理结束时执行回调,让它处理清理。

要注意的一件事是:如果你试图通过你的列表处理事物,然后尝试从另一个线程的列表中删除一个项目,你会遇到问题。你应该保留一个标志(以线程安全的方式访问),一旦你开始处理列表中的所有内容,忽略你得到的任何回调。

答案 1 :(得分:3)

这是一个粗略的草图:

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();
    }
}