我有一个相当复杂的多线程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();
}
}
答案 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();
}
}