С++ - _beginthreadex() не запускает поток

Я немного запутался здесь, почему _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.

Почему нить никогда не запускается, другими словами, почему я не вижу, как MessageBoxA() появляется на моем экране, когда _beginthreadex() передается? Невозможно использовать _beginthreadex() в DLL файле или что?

РЕДАКТИРОВАТЬ № 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 или остальном его содержимом?

Итак, при условии, что эти выводы, что мне делать? Как я могу решить эту проблему?

+3
19 сент. '15 в 22:16
источник поделиться
1 ответ

Вот два простых примера, которые компилируются и запускаются в Visual Studio 2012 в качестве консольного приложения. Создайте простое консольное приложение Windows, а затем вставьте этот исходный код в файл. Существует не так много способов обнаружения ошибок, однако основные части работают.

_beginthreadex() предоставляет оболочку для CreateThread() в Windows API, однако документация указывает, что она выполняет необходимое инициирование для времени выполнения C/С++ как часть запуска потока. Смотрите потоки Windows: _beginthread vs _beginthreadex vs CreateThread С++, чтобы узнать о различиях между этими тремя способами запуска потока в Windows.

Запуск потока используется в 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 exit code so that we can print it out
    CloseHandle (hThread);                         // We be done with the thread so close out it 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 exit code so that we can print it out
    CloseHandle (hThread);                         // We be done with the thread so close out it 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;
}

Несколько потоков

Если простое приложение изменено, чтобы иметь петли в потоках с выходом, мы могли бы иметь несколько одновременных потоков. Главное можно было бы изменить так, чтобы выглядеть следующим образом, когда мы запускаем два разных потока, которые мы заинтересованы в управлении, а затем дождаемся, пока они закончатся, а затем проверьте статус выхода обоих потоков следующим образом. Существует третий поток, который запускается, но мы не должны оба обрабатывать его и управлять им. Он заканчивается через короткое время.

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 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 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 handle to release resources
    CloseHandle (hThreads[1]);                         // We be done with the thread so close out it handle to release resources
    return 0;
}

Каждый из трех потоков имеет простой цикл, который рассчитывает до конечного значения и отображает сообщение для стандартного вывода. A 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;
}

На выходе отображаются все различные потоки, запущенные с подсчетом. Обратите внимание, что поток 3, который был запущен потоком 2, продолжает работать после завершения потока 2 из-за задержки запуска его цикла. Оба потока 2 и поток 3 находятся в коде DLL и запускаются, когда главный вызов вызывает точку входа DLL Function1().

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
+3
19 сент. '15 в 23:04
источник

Посмотрите другие вопросы по меткам или Задайте вопрос