【问题标题】:Why win api thread executes function, but standard thread does not?为什么win api线程执行函数,而标准线程不执行?
【发布时间】:2019-03-12 22:48:37
【问题描述】:

我有 15 个线程,我想执行我推送的 10 个函数。我现在不在乎保护它,只是想知道为什么win api执行功能,而std没有。

代码或多或少来自手工制作的英雄日 123

struct WorkQueueEntry
{
    char* stringToPrint;
};
static uint32 nextEntryToDo;
static uint32 entryCount;
WorkQueueEntry entries[256];

inline void PushString(const char* string)
{
    WorkQueueEntry* entry = entries + entryCount++;
    entry->stringToPrint = const_cast<char*>(string);
}

struct ThreadInfo
{
    int logicalThreadIndex;
};

DWORD WINAPI ThreadProc(LPVOID lpParameter)
{
    printf("entry count %i, nextEntryToDo %i\n", entryCount, nextEntryToDo);
    ThreadInfo* threadInfo = (ThreadInfo*)lpParameter;
    for(;;) {
        if(nextEntryToDo < entryCount) {
            WorkQueueEntry* entry = entries + nextEntryToDo++;
            char buffer[256];
            sprintf_s(buffer, "Thread %u: %s", threadInfo->logicalThreadIndex, entry->stringToPrint);
            printf(buffer);
        }
    }
}

主要的某处

#define WinThread


ThreadInfo threadInfo[5];
    for(int i = 0; i < _ARRAYSIZE(threadInfo); ++i) {
        ThreadInfo* info = threadInfo + i;
        info->logicalThreadIndex = i;

        #ifdef WinThread
        {
            DWORD threadID;
            HANDLE threadHandle = CreateThread(0, 0, ThreadProc, info, 0, &threadID);
            CloseHandle(threadHandle);
        }
        #else
        {
            std::thread t(ThreadProc, info);
            t.join();
        }
        #endif
    }

    PushString("String 0\n");
    PushString("String 1\n");
    PushString("String 2\n");
    PushString("String 3\n");
    PushString("String 4\n");
    PushString("String 5\n");
    PushString("String 6\n");
    PushString("String 7\n");
    PushString("String 8\n");
    PushString("String 9\n");

win api线程显示app入口计数为10,所以if(nextEntryCount &lt; entryCount)为真,可以完成功能。 Std 线程在开始时的条目计数为 0,因此 if(nextEntryCount &lt; entryCount) 不正确并且 func 无法完成。

这是为什么呢?

在创建 std 线程之前推送字符串可以修复它,但并不完全正确。

现在看起来像这样:

//#define WinThread

PushString("String 0\n");
PushString("String 1\n");
PushString("String 2\n");
PushString("String 3\n");
PushString("String 4\n");
PushString("String 5\n");
PushString("String 6\n");
PushString("String 7\n");
PushString("String 8\n");
PushString("String 9\n");

ThreadInfo threadInfo[5];
    for(int i = 0; i < _ARRAYSIZE(threadInfo); ++i) {
        ThreadInfo* info = threadInfo + i;
        info->logicalThreadIndex = i;

        #ifdef WinThread
        {
            DWORD threadID;
            HANDLE threadHandle = CreateThread(0, 0, ThreadProc, info, 0, &threadID);
            CloseHandle(threadHandle);
        }
        #else
        {
            std::thread t(ThreadProc, info);
            t.join();
        }
        #endif
    }

开始时条目计数为 10,并且 if(nextEntryCount

为什么,使用标准线程,只有一个线程完成所有工作?

【问题讨论】:

    标签: c++ multithreading winapi std


    【解决方案1】:

    t.join() 让你阻止直到t 完成。 CloseHandle(threadHandle) 没有相同的效果(它关闭句柄但不在线程上等待)。

    如果您希望 std::thread 匹配 WinAPI 线程,请在 join 之前创建它们中的任何一个。最简单的解决方案是放弃线程的所有权而不等待它,方法是将t.join() 替换为t.detach()

    【讨论】:

    • 如果你加入 WinApi 线程,WaitForSingleObject(和朋友)。
    • 哦,我知道了,谢谢。执行所有 10 个功能的一个 std 线程怎么样?
    • @JarekBisnesu:那是因为join。您启动一个线程,然后等待它从队列中拉出 10 个工作项中的每一个并执行它们,然后退出,此时 join 最终返回。剩下的线程全部依次启动,发现无事可做(因为第一个线程全部搞定了),立即退出。
    • @JarekBisnesu: detachjoin 是互斥的(它们都需要 joinable thread,并且它们都渲染了 thread 他们被称为非joinable),所以你只能使用其中一个。从技术上讲,使用detachalmost certain to invoke undefined behavior 无需付出太多努力,但如果您以某种方式保证线程在main 退出时没有做任何重要的事情,它是最无害的未定义行为。
    • @JarekBisnesu:要将join 用于完全定义的行为,您需要在创建它们时存储所有线程,然后将join 它们全部存储在存储循环中,例如制作std::thread allthreads[_ARRAYSIZE(threadInfo)];,然后在现有循环中执行allthreads[i] = std::thread(ThreadProc, info);,然后在现有循环之后制作一个新循环,该循环仅执行for (auto&amp;&amp; t : allthreads) t.join(); 之类的操作。在现实生活中,我可能会使用vectorreserveemplace_back 来完成所有这些,而不是堆栈数组,但它应该可以工作;我只是按照你现有的代码。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2018-04-01
    • 2017-06-19
    • 2021-10-16
    • 1970-01-01
    • 1970-01-01
    • 2021-05-08
    相关资源
    最近更新 更多