繁体   English   中英

C ++ - _beginthreadex()不启动该线程

[英]C++ - _beginthreadex() doesn't start the thread

我在这里有点困惑,为什么_beginthreadex()不会启动我的线程。 基本上,我有一个主题:

编辑#3 - 添加了while(),作为我的代码的一部分,但我从来没有说过,因此这个线程必须始终运行,直到在其中提示退出代码。 它必须与我的实际应用程序一起运行(因此,我实际上不能WaitForSingleObject(HANDLE, INFINITE)

unsigned int WINAPI MyThread1(LPVOID)
{  
     MessageBoxA(0, "We're in!", 0, 0);
     while (TRUE)
     {
          // do something
     }
}

我有我的_beginthreadex()代码:

/*
   take note that, this is inside another function, and that function is also 
   called through a seperate _beginthreadex() call, so basically, this thread
   is supposed to be called from within another thread
*/
if (user.settingsPage.ChangeVolume > 0)
{
   _beginthreadex(0, 0, &MyThread1, 0, 0, 0);
   // do some cleanup here, of non-related things
}

此文件是DLL扩展名。

换句话说,为什么线程不会运行,换句话说,当传递_beginthreadex()时,为什么我没有看到MessageBoxA()出现在我的屏幕上? 是不是可以在DLL文件中使用_beginthreadex() ,或者是什么?

编辑#1

我已经实施了Richard Chambers在回复中所说的话。

我从GetExitCodeThread()了错误代码,并在MessageBoxA()输出,错误代码输出为259

查看MSDN系统错误代码列表后: 此处

错误代码对应于以下内容:

ERROR_NO_MORE_ITEMS
259 (0x103)
No more data is available.

编辑#2

我在这里阅读,我注意到这个文本If a thread returns STILL_ACTIVE (259) as an error code, applications that test for this value could interpret it to mean that the thread is still running and continue to test for the completion of the thread after the thread has terminated, which could put the application into an infinite loop. - 这与我的问题有什么关系吗? 如果是这样, the thread is still running它意味着什么? 如果它已经在运行,那么为什么我在MessageBox或其余内容中看不到它的任何输出?

所以,提供这些结论,我该怎么办? 我该如何解决这个问题?

以下是在Visual Studio 2012中作为控制台应用程序编译和运行的两个简单示例。 创建一个简单的Windows控制台应用程序,然后将此源代码粘贴到该文件中。 然而,错误检测的方式并不多,但主要部分仍然有效。

_beginthreadex()在Windows API中为CreateThread() _beginthreadex()提供了一个包装器,但是文档表明它在启动线程时为C / C ++运行时进行了必要的启动。 有关在Windows中启动线程的这三种方法之间的差异的详细信息,请参阅Windows线程:_beginthread vs _beginthreadex与CreateThread C ++

启动一个线程始终在DLL和COM对象中使用,因此还有其他错误。 以下示例一次启动一个线程。

    // threadtest.cpp : Defines the entry point for the console application.
    //

    #include "stdafx.h"

    // necessary include files for a Console application wanting to do some Windows things with threads.
    // ordinarily #include <Windows.h> would be added to stdafx.h for this Console application.
    //   Windows.h provides things such as the Sleep() function as well as definitions for HANDLE, etc.
    //   process.h provides the prototypes and declarations for _beginthreadex()
    //   iostream with no .h provides the C++ Standard Library I/O routines for std::cout
    #include <Windows.h>
    #include <process.h>

    #include <iostream>

    // list of arguments to provide to the thread being started up.
    struct argList {
        int i1;
        int i2;
        int i3;
    };

    unsigned int WINAPI myThread (void * args)
    {
        argList *pArgs = (argList *)args;  // convert the LPVOID to the proper type to access the arguments.

        // a bit of output to let us know we got here then a sleep to slow things down a touch.
        std::cout << "myThread is running? args " << pArgs->i1 << ", " << pArgs->i2 << ", " << pArgs->i3 << std::endl;

        Sleep(1000);

        // add the arguments and return the sum.
        return (pArgs->i1 + pArgs->i2 + pArgs->i3);
    }

// declare the function in the DLL we are going to call.
__declspec(dllimport) HANDLE __cdecl Function1(void);

int _tmain(int argc, _TCHAR* argv[])
{
    HANDLE   hThread;
    DWORD    exitCode;
    argList myArgs = {1, 2, 3};

    std::cout << "main is running?" << std::endl;

    // start a thread with the arguments we want to sum and wait for it to complete and return to us.
    // when it returns we will fetch the return value which is the sum of the arguments.

    hThread = (HANDLE)_beginthreadex (0, 0, myThread, &myArgs, 0, 0);
    WaitForSingleObject (hThread, INFINITE);       // Wait for the thread we started to complete, a kind of Join
    GetExitCodeThread (hThread, &exitCode);        // Get the thread's exit code so that we can print it out
    CloseHandle (hThread);                         // We be done with the thread so close out it's handle to release resources

    std::cout << "main ending, thread exit code " << exitCode << std::endl;

    // now call the function in our DLL which will start up a thread there
    // get its handle so that we can check the exit code, etc.
    hThread = Function1();
    WaitForSingleObject (hThread, INFINITE);       // Wait for the thread we started to complete, a kind of Join
    GetExitCodeThread (hThread, &exitCode);        // Get the thread's exit code so that we can print it out
    CloseHandle (hThread);                         // We be done with the thread so close out it's handle to release resources
    std::cout << "main ending, Function1 exit code " << exitCode << std::endl;
    return 0;
}

使用标准的添加向导将一个简单的控制台DLL项目添加到Visual Studio 2012解决方案中。 我修改了什么是空文件,而不是包含用于附加的DLL消息处理程序的DLL主文件。修改后的文件包含以下内容:

#include "stdafx.h"

#include <Windows.h>

#include <process.h>
#include <iostream>

unsigned int WINAPI myThread2 (void * args)
{

    // a bit of output to let us know we got here then a sleep to slow things down a touch.
    std::cout << "myThread2 is running? args " << std::endl;

    MessageBox (0, L"A message2  text", L"Caption 2", 0);
    Sleep(1000);

    // add the arguments and return the sum.
    return 345;
}

__declspec(dllexport) HANDLE __cdecl Function1(void)
{
    std::cout << " in DLL, starting thread." << std::endl;

    HANDLE hThread = (HANDLE)_beginthreadex (0, 0, myThread2, 0, 0, 0);

    return hThread;
}

多线程

如果简单的应用程序被修改为在具有输出的线程中具有循环,那么我们可以同时运行多个线程。 main可以修改为如下所示,我们启动两个不同的线程,我们有兴趣管理,然后等待两个完成然后检查两个线程的退出状态,如下所示。 有一个第三个线程启动但是我们不是既得到它的处理也不管理它。 它会运行很短的时间然后结束。

int _tmain(int argc, _TCHAR* argv[])
{
    HANDLE          hThreads[2];
    DWORD           exitCode;
    unsigned int    threadId;
    argList myArgs = {1, 2, 3};

    std::cout << "main is running?" << std::endl;

    // start a thread with the arguments we want to sum and wait for it to complete and return to us.
    // when it returns we will fetch the return value which is the sum of the arguments.

    hThreads[0] = (HANDLE)_beginthreadex (0, 0, myThread, &myArgs, 0, &threadId);
    hThreads[1] = Function1();

    WaitForMultipleObjects  (2, hThreads, TRUE, INFINITE);       // Wait for all threads we started to complete, a kind of Join
    GetExitCodeThread (hThreads[0], &exitCode);        // Get the thread's exit code so that we can print it out
    std::cout << "main ending, thread 1 exit code " << exitCode << std::endl;
    GetExitCodeThread (hThreads[1], &exitCode);        // Get the thread's exit code so that we can print it out
    std::cout << "main ending, thread 2 exit code " << exitCode << std::endl;
    CloseHandle (hThreads[0]);                         // We be done with the thread so close out it's handle to release resources
    CloseHandle (hThreads[1]);                         // We be done with the thread so close out it's handle to release resources
    return 0;
}

三个线程中的每一个都有一个简单的循环,它计数到最终值并向标准输出显示一条消息。 Sleep(1000)让我们有办法减慢一切。 所以每个线程都有一个如下所示的循环,它来自3号线程。

MessageBox (0, L"A message 3  text", L"Caption 3", 0);

std::cout << "    myThread 3 after MessageBox - start loop" << std::endl;

for (int i = 0; i < 10; i++) {
    Sleep(1000);
    std::cout << "    myThread 3 is running step "<< i << std::endl;
}

std::cout << "myThread 3 end" << std::endl;

此示例的DLL源在导出的入口点Function1()启动一个线程,而在Function1()启动的线程启动第三个线程。

#include "stdafx.h"

#include <Windows.h>

#include <process.h>
#include <iostream>

unsigned int WINAPI myThread3 (void * args)
{
    // a bit of output to let us know we got here then a sleep to slow things down a touch.
    std::cout << "myThread3 is running? args " << std::endl;

    MessageBox (0, L"A message 3  text", L"Caption 3", 0);

    std::cout << "    myThread 3 after MessageBox - start loop" << std::endl;

    for (int i = 0; i < 10; i++) {
        Sleep(1000);
        std::cout << "    myThread 3 is running step "<< i << std::endl;
    }

    std::cout << "myThread 3 end" << std::endl;
    return 2356;
}

unsigned int WINAPI myThread2 (void * args)
{

    // a bit of output to let us know we got here then a sleep to slow things down a touch.
    std::cout << "myThread2 is running? args " << std::endl;

    MessageBox (0, L"A message 2  text", L"Caption 2", 0);

    std::cout << "    myThread 2 after MessageBox - start myThread3 then loop" << std::endl;

    HANDLE hThread = (HANDLE)_beginthreadex (0, 0, myThread3, 0, 0, 0);

    for (int i = 0; i < 10; i++) {
        Sleep(1000);
        std::cout << "    myThread 2 is running "<< i << std::endl;
    }

    std::cout << "myThread 2 end" << std::endl;
    // add the arguments and return the sum.
    return 345;
}

__declspec(dllexport) HANDLE __cdecl Function1(void)
{
    std::cout << " in DLL, starting myThread 2." << std::endl;

    HANDLE hThread = (HANDLE)_beginthreadex (0, 0, myThread2, 0, 0, 0);

    return hThread;
}

输出显示运行计数的所有各种线程。 请注意,在输出中,由于延迟启动循环,线程2在线程2结束后继续运行。 线程2和线程3都在DLL代码中,并在main调用Function1()的DLL入口点时启动。

main is running?
 in DLL, starting myThread 2.
myThread is running? args myThread2 is running? args 1, 2, 3

    myThread after MessageBox - start loop
    myThread is running i = 0
    myThread is running i = 1
    myThread 2 after MessageBox - start myThread3 then loop
myThread3 is running? args
    myThread is running i = 2
    myThread 2 is running 0
    myThread is running i = 3
    myThread 2 is running 1
    myThread is running i = 4
    myThread 3 after MessageBox - start loop
    myThread 2 is running 2
    myThread is running i = 5
    myThread 3 is running step 0
    myThread 2 is running 3
    myThread is running i = 6
    myThread 3 is running step 1
    myThread 2 is running 4
    myThread is running i = 7
    myThread 3 is running step 2
    myThread 2 is running 5
    myThread is running i = 8
    myThread 3 is running step 3
    myThread 2 is running 6
    myThread is running i = 9
    myThread 3 is running step 4
    myThread 2 is running 7
    myThread is running i = 10
    myThread 3 is running step 5
    myThread 2 is running 8
    myThread is running i = 11
    myThread 3 is running step 6
    myThread 2 is running 9
myThread 2 end
    myThread is running i = 12
    myThread 3 is running step 7
    myThread is running i = 13
    myThread 3 is running step 8
    myThread is running i = 14
    myThread 3 is running step 9
myThread 3 end
    myThread is running i = 15
    myThread is running i = 16
    myThread is running i = 17
    myThread is running i = 18
    myThread is running i = 19
myThread end
main ending, thread 1 exit code 6
main ending, thread 2 exit code 345

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM