【问题标题】:Windows handling CTRL+C in different thread?Windows 在不同的线程中处理 CTRL+C?
【发布时间】:2011-11-16 06:40:39
【问题描述】:

这是一个在 linux 和 windows 上处理 CTRL+C 信号的简单应用程序:

#include <QtCore/QCoreApplication>
#include <QDebug>
#include <QThread>

void SigIntHandler()
{
    qDebug()<<"SigInt ThreadID: "<<QThread::currentThreadId();
    qApp->quit();
}

#ifdef __linux__
#include <signal.h>

    void unix_handler(int s)
    {
        //svakako je SIGINT, ali da ne javlja warning da se s ne koristi
        if (s==SIGINT)
            SigIntHandler();
    }

#else
#include <windows.h>

    BOOL WINAPI WinHandler(DWORD CEvent)
    {
        switch(CEvent)
        {
        case CTRL_C_EVENT:
            SigIntHandler();
            break;
        }
        return TRUE;
    }

#endif

int main(int argc, char *argv[])
{
    QCoreApplication a(argc, argv);


    //kod za hvatanje CTRL+C - unix i windows
    #ifdef __linux__
        signal(SIGINT, &unix_handler);
    #else
        SetConsoleCtrlHandler((PHANDLER_ROUTINE)WinHandler, TRUE);
    #endif

    qDebug()<<"Main ThreadID: "<<QThread::currentThreadId();
    return a.exec();
}

在 linux (Debian Squeeze) 上编译并运行后,我得到以下输出:

/Test-build-desktop$ ./Test 
Main ThreadID:  140105475446560 
^CSigInt ThreadID:  140105475446560 

/Test-build-desktop$ ./Test 
Main ThreadID:  140369579480864 
^CSigInt ThreadID:  140369579480864 

/Test-build-desktop$ ./Test 
Main ThreadID:  140571925509920 
^CSigInt ThreadID:  140571925509920 

这就是我所期望的(SigIntHandler 方法在主线程上运行)。但是当我在 Windows 7 上编译和执行相同的代码时,我得到了这个:

d:\Test-build-desktop\debug>Test.exe
Main ThreadID:  0x5a8
SigInt ThreadID:  0x768

d:\Test-build-desktop\debug>Test.exe
Main ThreadID:  0x588
SigInt ThreadID:  0x1434

d:\Test-build-desktop\debug>Test.exe
Main ThreadID:  0x1170
SigInt ThreadID:  0xc38

如您所见,这里的 SigIntHandler 方法是在不同的线程中执行的,然后是 main ... 这给我带来了很多问题。所以我的问题是 - 是否可以强制 SigIntHandler 在 windows 的主线程中运行?我可能会发现信号错误吗?

谢谢!!

【问题讨论】:

    标签: c++ windows multithreading qt signals


    【解决方案1】:

    来自MSDN topic HandlerRoutine

    HandlerRoutine 函数是与SetConsoleCtrlHandler 函数一起使用的应用程序定义函数。控制台进程使用此函数来处理进程接收到的控制信号。收到信号后,系统在进程中创建一个新线程来执行函数。

    所以,答案是:这是不可能的。

    【讨论】:

    • uf ... 微软总是很特别 :( 感谢您提供信息 ;)
    • 这不是不可能的。在由 SetConsoleCtrlHandler 函数(在新线程中运行)设置的处理程序例程中,您可以使用 SetThreadContext 函数操作主线程。这不适合胆小的人,并且需要一些组装知识,但这是可能的。并不是说您希望在这方面以 Unix 的方式工作。
    • 事实上,微软再次以正确的方式做到了这一点。信号是 Unix 上最糟糕的特性之一。无需为每个函数等定义信号异步安全性。最后,在 unix 上的非平凡程序中,您通常只会增加一个信号量来运行另一个可以完成实际工作的线程。
    【解决方案2】:

    阅读以下链接,了解有趣的观点:http://blogs.msdn.com/b/oldnewthing/archive/2008/07/28/8781423.aspx

    【讨论】:

    • 感谢您的评论 :) 读完这篇文章后,似乎 windows 方式确实更好......无论如何,我不在乎,我已经将我的程序固定在 linux 上的工作台上和窗户 :)
    猜你喜欢
    • 2021-12-23
    • 1970-01-01
    • 1970-01-01
    • 2012-03-20
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2013-08-19
    • 2013-12-05
    相关资源
    最近更新 更多