【问题标题】:WINAPI CreateThread not always running threadWINAPI CreateThread 并不总是运行线程
【发布时间】:2016-03-25 06:40:45
【问题描述】:

我正在尝试使用 Windows CreateThread API 创建和执行线程。我看到运行程序会产生不确定的行为。我从程序的输出中看到,有时线程方法“my”被执行,有时不被执行。这可能是什么原因?该程序非常简单,如下所示。还有应该用什么来初始化 dwThreadID。它应该是 0 还是任何整数值? PS:在Visual Studio中编译。

#include "stdafx.h"
#include <iostream>  
#include <windows.h>  
using namespace std;

// DWORD WINAPI   
DWORD  WINAPI my (LPVOID lpParam ) {  
    for (int i = 0; i < 5;i++){  
        cout << "I am ";  
    } 
    return 0; 
} 

int main()  
{
    DWORD dwThreadID = 0;   
    DWORD dwThrdParam = 0;  
    HANDLE h = NULL; 
    h = CreateThread(
            NULL,              // default security
            0,                 // default stack size
            my,        // name of the thread function
            0,              // no thread parameters
            0,                 // default startup flags
            &dwThreadID); 
     if (h == NULL){  
         cout <<"It is null";
     }      
    cout << " BBBB" << endl ;  
    CloseHandle(h); 
    cout << "BBBB "; 
    return 0;  
}

【问题讨论】:

  • 更具体地说,当我运行程序时,有时我得到的输出为 -
  • 特别是当我运行这个程序时,有时我得到的输出只是 BBB BBB。我什至没有看到“我在”被打印一次,这表明我的方法没有被执行。 GetLastError 也总是返回 0
  • 你需要等待线程结束。

标签: c++ windows multithreading visual-studio winapi


【解决方案1】:

我从程序的输出中看到,有时线程 方法“我的”被执行,有时不被执行。可能是什么原因 为此?

你的主线程可能在你的第二个线程执行之前就退出了。调用CreateThread后放置断点。

或者更干净的等待,只需使用WaitForSingleObject 等待第二个线程。 这有效地使您的主线程等待“我的”线程完成。

如果CreateThread由于某种原因失败了,你可以在CreateThread之后直接调用GetLastError,它会给你最终的答案。

还有应该用什么来初始化 dwThreadID。

快速查看MSDN 会产生以下结果:

指向接收线程标识符的变量的指针。

【讨论】:

  • 感谢您的回答。可能您的主线程在您的第二个线程甚至执行之前就退出了。使用 WaitForSingleObject 后,它现在可以工作了。
【解决方案2】:

你的线程是否执行是不确定的。主线程创建它,然后终止程序。可能会发生以下情况:

  • 线程可能在主线程终止之前执行。
  • 程序可能在线程执行之前终止。
  • 线程可能部分执行并在程序终止时终止。

您需要添加同步以确保线程完成。将线程句柄传递给WaitForSingleObject

您的程序不检查错误。 CreateThread 失败时返回 NULL。如果发生这种情况,并且仅当这种情况发生时,请致电GetLastError 以获取有关函数失败原因的信息。如果您添加对WaitForSingleObject 的调用,则应按照文档中的说明检查其返回值是否存在错误。

dwThreadID 应该用什么初始化?

它不需要初始化,因为CreateThread 保证如果CreateThread 成功,它将被分配。

【讨论】:

    【解决方案3】:

    首先不要使用CreateThread,它是供图书馆提供者使用的。使用beginthreadexstd::thread

    可能的行为是线程始终运行,但它的输出被覆盖。这是因为没有同步。

    检查返回码和GetLastError

    dwThreadid 的值无所谓

    【讨论】:

    • 请注意,通过使用beginthreadex,您可以使您的程序依赖于 MSVCRT。
    • @mksteve 不,不是。运行时已与 CreateThread 兼容多年。
    • 来自 msdn "可执行文件中调用 C 运行时库 (CRT) 的线程应该使用 _beginthreadex 和 _endthreadex 函数进行线程管理,而不是 CreateThread 和 ExitThread;这需要使用多线程CRT 的版本。如果使用 CreateThread 创建的线程调用 CRT,CRT 可能会在内存不足的情况下终止进程。"。具有 TLS 的函数(例如 strtok)创建 TLS 结构。使用 CreateThread 会导致它被延迟到使用。引起exit 来电。开始线程在末尾添加代码以清理 TLS 内存
    • @mksteve 该文档已过时,多年来一直不相关。该限制与系统线程池不兼容,因此更改了 CRT。 stackoverflow.com/questions/2100589/beginthread-vs-createthread 这是一种不会消失的货物崇拜信仰。我完全希望 20 年后能在这里与我们的孩子进行同样的对话!
    猜你喜欢
    • 2018-12-05
    • 2018-01-14
    • 2016-03-29
    • 1970-01-01
    • 2014-01-30
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多