【发布时间】:2009-06-10 13:36:11
【问题描述】:
我有一个基于控制台的QCoreApplication,它有计时器并进行套接字通信,还使用锁定的互斥锁。
当我手动关闭应用程序时,它会给出错误消息,指出某些互斥锁已锁定并且已超时。当用户关闭控制台应用程序时,有什么方法可以在控制台应用程序中进行清理吗?
【问题讨论】:
我有一个基于控制台的QCoreApplication,它有计时器并进行套接字通信,还使用锁定的互斥锁。
当我手动关闭应用程序时,它会给出错误消息,指出某些互斥锁已锁定并且已超时。当用户关闭控制台应用程序时,有什么方法可以在控制台应用程序中进行清理吗?
【问题讨论】:
清理应该由析构函数和子父关系来处理。
使您的主对象(主对象)成为 QApplication 的子对象,以便在 QApplication 之前将其与所有子对象一起销毁。
你确定你杀死了你所有的线程吗?如果是带有事件循环的线程,请务必在调用QThread::wait() 之前调用QThread::quit() 退出事件循环
您也可以使用 void QApplication::qAddPostRoutine ( QtCleanUpFunction ptr )
做一些特殊的清理工作。
要调试这些消息,您可以使用QtMsgHandler qInstallMsgHandler ( QtMsgHandler h ) 并编写自己的消息处理程序来捕获这些警告。如果您可以模拟问题,您可以在消息上设置断点并查看消息来自的堆栈。
void debugMessageHandler( QtMsgType type, const char *msg ){
if(QString(msg).contains( "The message you can see in the console" )){
int breakPointOnThisLine(0);
}
switch ( type ) {
case QtDebugMsg:
fprintf( stderr, "Debug: %s\n", msg );
break;
case QtWarningMsg:
fprintf( stderr, "Warning: %s\n", msg );
break;
case QtFatalMsg:
fprintf( stderr, "Fatal: %s\n", msg );
abort();
}
}
为了清理析构函数和子父关系,您可以捕获控制台关闭信号并将QCoreApplication::exit() 调用到应用程序实例。
#include <csignal>
#include <QtCore/QCoreApplication>
using namespace std;
struct CleanExit{
CleanExit() {
signal(SIGINT, &CleanExit::exitQt);
signal(SIGTERM, &CleanExit::exitQt);
signal(SIGBREAK, &CleanExit::exitQt) ;
}
static void exitQt(int sig) {
QCoreApplication::exit(0);
}
};
int main(int argc, char *argv[])
{
CleanExit cleanExit;
QCoreApplication a(argc, argv);
return a.exec();
}
【讨论】:
signal(SIGTERM, [](int sig){ qApp->quit(); });
事实证明,通过按“关闭”(标题栏上的红色 x 按钮)关闭命令行应用程序(在 Win7 和 VS2010 上检查)会将STATUS_CONTROL_C_EXIT 信号传递给应用程序。所有线程都使用此代码中止。
线程“主线程”(0x980) 已退出,代码为 -1073741510 (0xc000013a)。
线程 'QThread' (0x2388) 已退出代码 -1073741510 (0xc000013a)。
这意味着没有办法用QCoreApplication::aboutToQuit() 信号拦截它。
看看winnt.h 或ntstatus.h。那就是分配给
清单常量STATUS_CONTROL_C_EXIT。运行时只是
选择使用代码结束程序以记录用户的取消
操作。
【讨论】:
您可以连接到QCoreApplication::aboutToQuit 信号并在那里进行必要的清理。
【讨论】: