有没有一种便携的方式在Qt中设置线程名?

7
我知道在Linux中可以使用prctl()设置线程名称(在gdb和htop中可见)。但在其他操作系统中,这可能不起作用。另外,我可以尝试使用pthread_setname_np(),它在POSIX系统中更加普遍,但仍然缺乏完全兼容性。
因此,我希望有一种更便携的方法,也许是QThread提供的,但我还没有找到。是否有这样的方法?

你可以根据你所编译的操作系统使用编译标志来工作。 - Theolodis
Boost没有这样的方式,所以我怀疑QT也不会有。 - ratchet freak
2个回答

9

QThread API中,没有手动管理线程系统名称的功能。但是,自从4.8.3版本以来,Qt会自动将您的线程名称设置为线程对象的名称(QObject::objectName())。

这在QThread的实现中处理如下所述。

qthread_unix.cpp中有类似以下内容:

#if (defined(Q_OS_LINUX) || defined(Q_OS_MAC) || defined(Q_OS_QNX))
static void setCurrentThreadName(pthread_t threadId, const char *name)
{
#  if defined(Q_OS_LINUX) && !defined(QT_LINUXBASE)
    Q_UNUSED(threadId);
    prctl(PR_SET_NAME, (unsigned long)name, 0, 0, 0);
#  elif defined(Q_OS_MAC)
    Q_UNUSED(threadId);
    pthread_setname_np(name);
#  elif defined(Q_OS_QNX)
    pthread_setname_np(threadId, name);
#  endif
}
#endif

/* 
 * [...]
 */

QString objectName = thr->objectName();

if (Q_LIKELY(objectName.isEmpty()))
    setCurrentThreadName(thr->d_func()->thread_id, thr->metaObject()->className());
else
    setCurrentThreadName(thr->d_func()->thread_id, objectName.toLocal8Bit());

qthread_win.cpp中的等效代码:

typedef struct tagTHREADNAME_INFO
{
    DWORD dwType;      // must be 0x1000
    LPCSTR szName;     // pointer to name (in user addr space)
    HANDLE dwThreadID; // thread ID (-1=caller thread)
    DWORD dwFlags;     // reserved for future use, must be zero
} THREADNAME_INFO;

void qt_set_thread_name(HANDLE threadId, LPCSTR threadName)
{
    THREADNAME_INFO info;
    info.dwType = 0x1000;
    info.szName = threadName;
    info.dwThreadID = threadId;
    info.dwFlags = 0;

    __try
    {
        RaiseException(0x406D1388, 0, sizeof(info)/sizeof(DWORD), (const ULONG_PTR*)&info);
    }
    __except (EXCEPTION_CONTINUE_EXECUTION)
    {
    }
}

/* 
 * [...]
 */

QByteArray objectName = thr->objectName().toLocal8Bit();
qt_set_thread_name((HANDLE)-1, objectName.isEmpty() ? thr->metaObject()->className() : objectName.constData());

请注意,在Windows上,如果设置了QT_NO_DEBUG,则上述代码不会被执行,因此发布模式下无法工作

这似乎只适用于足够新的Qt版本。我在4.8.1中没有看到@Marek引用的行为。相反,我的所有线程都与二进制文件名相符。此外,在发行版提供的源代码树中搜索“setCurrentThreadName”并没有找到任何内容。无论如何,这似乎是Qt中第一个真正支持此功能的版本,所以我会接受你的答案。 - Ruslan
@Ruslan 是的,正如您在这里所看到的那样,该功能是为了调试目的而实现的。我很惊讶它被引用在Qt文档中,因为它不过是一个调试解决方法而已。 - zakinster

7
Qt文档中,您可以找到以下内容:

要选择您的线程将被赋予的名称(例如在Linux上通过命令ps -L识别),您可以在启动线程之前调用setObjectName()。如果您不调用setObjectName(),则会将运行时类型的线程对象的类名作为线程名称(例如,在Mandelbrot示例中,该名称为QThread子类的“RenderThread”)。请注意,这在Windows的发布版本中目前不可用。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接