假设我有一个 C++0x 中的消息泵类,如下所示(请注意,SynchronizedQueue 是一个函数队列 <void()>,当您在队列上调用 receive() 并且它为空时,它会阻塞调用线程,直到有一个项目返回):
我已将这个类转换为C#,但是对于析构函数中的代码我有一个问题。根据IDisposable模式,我应该只提供一个Dispose()方法以释放托管和非托管资源。
我应该将C++析构函数代码放在以下哪个位置:
1.自定义CleanUp()方法,客户端需要在应用程序退出时调用它?如果客户端忘记了怎么办?
2.IDisposable的Dispose()方法中,以便客户端也可以调用它?但是,如果客户端忘记了呢?
3.在C#终结器方法中,以便它总是执行?我读到如果你没有任何非托管资源,就不应该包含终结器方法,因为会影响性能。
4.不放在任何地方?只需忽略标记done_标志并让GC自然处理,因为Thread对象是托管资源?线程会被强制中止吗?
此外,我还发现如果我不将构造函数中创建的消息泵线程标记为后台线程,我的MessagePump对象永远不会被GC,当应用程序退出时会卡住。这是什么原因?
class MessagePump
{
private:
bool done_;
Thread* thread_;
SynchronizedQueue queue_;
void Run()
{
while (!done)
{
function<void()> msg = queue_.receive();
msg();
}
}
public:
MessagePump():
done_(false)
{
thread_ = new thread ([=] { this->Run(); } ) );
}
~MessagePump()
{
Send( [&]{ done = true; } );
thread_->join();
}
void Send (function<void()> msg)
{
queue_.send(msg);
}
};
我已将这个类转换为C#,但是对于析构函数中的代码我有一个问题。根据IDisposable模式,我应该只提供一个Dispose()方法以释放托管和非托管资源。
我应该将C++析构函数代码放在以下哪个位置:
1.自定义CleanUp()方法,客户端需要在应用程序退出时调用它?如果客户端忘记了怎么办?
2.IDisposable的Dispose()方法中,以便客户端也可以调用它?但是,如果客户端忘记了呢?
3.在C#终结器方法中,以便它总是执行?我读到如果你没有任何非托管资源,就不应该包含终结器方法,因为会影响性能。
4.不放在任何地方?只需忽略标记done_标志并让GC自然处理,因为Thread对象是托管资源?线程会被强制中止吗?
此外,我还发现如果我不将构造函数中创建的消息泵线程标记为后台线程,我的MessagePump对象永远不会被GC,当应用程序退出时会卡住。这是什么原因?