簡體   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