线程未运行,为什么? [英] Threads not running, why?

查看:120
本文介绍了线程未运行,为什么?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我编写了一个简单的测试应用程序来证明线程可以正常工作:

I wrote a simple test application to prove that the threads work:

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

    #include "stdafx.h"

    class clsTest {
    private:
        uintptr_t muintHandle;

        static unsigned int __stdcall fnThread(void* pData) {
            while( 1 ) {
                _sleep(1000);
                printf("In fnThread, handle = %d\n", *(uintptr_t*)pData);
            }
            return 0;
        }
    public:
        clsTest() {
            muintHandle = _beginthreadex(0, 0, &clsTest::fnThread, (void*)&muintHandle, 0, 0);
            printf("clsTest(), after beginthreadex, handle = %u\n", muintHandle);
        }
    };

    int _tmain(int argc, _TCHAR* argv[]) {
        clsTest* pT = NULL;

        while(1) {
            printf("From _tmain\n");

            if ( pT == NULL ) {
                pT = new clsTest();
            }
            _sleep(1000);
        }
        return 0;
    }

此应用程序的输出为:

    From _tmain
    clsTest(), after beginthreadex, handle = 112
    In fnThread, handle = 112
    From _tmain
    In fnThread, handle = 112
    From _tmain
    In fnThread, handle = 112
    From _tmain
    In fnThread, handle = 112
    From _tmain
    In fnThread, handle = 112
    From _tmain
    In fnThread, handle = 112        
    ...

连续地,这正是我所希望看到的...现在在一个更大的项目中,我有了一个基类:

Continuously which is exactly what I would expect to see...Now in a much larger project I have a base class:

    typedef enum {
            eIdle = 0,      //Thread is not working at all
            eStarted,       //Thread has been started but is not fully operational yet
            eRunning,       //Thread is working normally
            ePausing,       //Thread is requested to enter the paused state
            ePaused,        //Thread is paused
            eTerminating    //Termination has been requested but not completed yet
        } eThreadStates; 

    class clsOpenLDVthread {
    protected:
        volatile eThreadStates meState;
        CRITICAL_SECTION mCritControl;  // critical section for thread control
        char mszName[80];
        HANDLE mhEvent, mhThread;
        virtual bool blnStart() = 0;

    public:
        clsOpenLDVthread(LPCSTR pszName);
        ~clsOpenLDVthread();

        bool inline blnIsRunning();
        bool inline blnIsStopped();
        bool inline blnIsStopping();
        bool inline blnIsStarting();
        bool inline blnIsPausing();
        bool inline blnIsPaused();
        bool blnPause(bool blnState);
        virtual bool blnStop();
    };

    clsOpenLDVthread::clsOpenLDVthread(LPCSTR pszName) : meState(eIdle)
                                               , mhThread(NULL) {
        ::InitializeCriticalSection(&mCritControl); //Get a critical section
        //Get a unique name for signaling event
        sprintf(mszName, "%s%d", pszName, ::GetCurrentProcessId());
        //Get the event object
        mhEvent = ::CreateEvent(NULL, FALSE, FALSE, mszName);
    }       
    clsOpenLDVthread::~clsOpenLDVthread() {
        if ( blnIsPaused() ) {
            blnPause(false);
        }
        if ( blnIsRunning() ) {
            blnStop();
        }
        if ( mhEvent ) {
            ::CloseHandle(mhEvent);
            mhEvent = NULL;
        }
        ::DeleteCriticalSection(&mCritControl);
    }
    bool clsOpenLDVthread::blnIsPaused() {
        return meState == ePaused;
    }
    bool clsOpenLDVthread::blnIsPausing() {
        return meState == ePausing;
    }
    bool clsOpenLDVthread::blnIsRunning() {
        return meState == eRunning;
    }
    bool clsOpenLDVthread::blnIsStarting() {
        return meState == eStarted;
    }
    bool clsOpenLDVthread::blnIsStopped() {
        return meState == eIdle;
    }
    bool clsOpenLDVthread::blnIsStopping() {
        return meState == eTerminating;
    }
    bool clsOpenLDVthread::blnPause(bool blnState) {
        bool blnResult = mhThread != NULL;
        if ( blnResult ) {
            if ( blnState ) {
                unsigned uintCountDown = 10u;

                if ( blnIsRunning() || blnIsPausing() ) {
                    meState = ePausing;
                    while( blnIsPausing() && -- uintCountDown ) {
                        ::SetEvent(mhEvent);
        //Give thread chance to run and pause
                        _sleep(751);
                    }
                    blnResult = blnIsPaused();
                }
            } else {
                if ( blnIsPaused() ) {
                    meState = eRunning;
                    //this will need replacing...mhThread->ResumeThread();
                }
                blnResult = true;
            }
        }
        return blnResult;
    }
    bool clsOpenLDVthread::blnStop() {
        bool blnResult = meState == eIdle;
        unsigned uintCountDown = 100u;

        if ( blnIsPaused() ) {
            blnPause(false);
        }
        if ( blnIsRunning() ) {
            meState = eTerminating;

            while( !blnIsStopped() && --uintCountDown ) {
                if ( mhEvent ) {
                    ::SetEvent(mhEvent);
                }
        //Give thread a change to run and terminate
                _sleep(501);
            }
            blnResult = blnIsStopped();
            mhThread = NULL;
        }
        return blnResult;
    }

最后是实现线程类并提供blnStart方法的派生类:

Finally a derived class that implements the thread class and provides the blnStart method:

    class clsOpenLDVrdr : public clsOpenLDVthread {
    public:
    //Maximum size of uplink data per single transfer
        static const unsigned mscuBuffersize;
    private:
    //The thread's main routine
        static void msgReaderThread(LPVOID lpParam);

    public:
        clsOpenLDVrdr();
        virtual ~clsOpenLDVrdr();
    //Call this to start the thread, see clsOpenLDVthread for more operations
        virtual bool blnStart();
    };

    const unsigned clsOpenLDVrdr::mscuBuffersize = MAX_OPENLDV_DATA;

    clsOpenLDVrdr::clsOpenLDVrdr() : clsOpenLDVthread(_T("EvOpenLDVrdr")) {
    }
    clsOpenLDVrdr::~clsOpenLDVrdr() {
    }
    bool clsOpenLDVrdr::blnStart() {
        bool blnResult = false;
        if ( blnIsStopped() ) {
            meState = eStarted;
        //Create the thread
            mhThread = (HANDLE)_beginthread(&clsOpenLDVrdr::msgReaderThread
                                            ,0, NULL);
            blnResult = mhThread != NULL;

            while( blnResult && (meState == eStarted) ) {
        //Give the thread chance to start and initialize
                _sleep(501);
            }
        }
        return blnResult && (meState == eRunning);
    }
    void clsOpenLDVrdr::msgReaderThread(LPVOID lpParam) {
            OutputDebugString("msgReaderThread\n");
    }

创建了类clsOpenLDVrdr的实例,并调用了blnStart方法:

An instance of the class clsOpenLDVrdr is created and the blnStart method called:

    clsOpenLDVrdr* pobjReader = new clsOpenLDVrdr();
    pobjReader->blnStart();

我可以在调试器中看到正在调用"blnStart"并逐步执行所有内容……但是该线程从未运行.

I can see in the debugger that "blnStart" is being called and stepping into it everything is executed...but the thread never runs.

还尝试使用_beginthreadex代替_beginthreadex:

Also tried using _beginthreadex instead of _beginthread:

    mhThread = (HANDLE)_beginthreadex(0, 0, pfnThread, pobParam, 0, 0);

没有区别.这里存在某种不兼容问题,因为我在本文开头创建的简单示例适用,并且两个版本之间没有太大区别.除了可能的使用方式之外...第一个简单的示例是作为Windows控制台应用程序创建的.我遇到的项目在DLL中.

No difference. There is some kind of incompatibility problem here as the simple example I created at the start of this post works and there isn't much difference between the two versions. Except maybe the way its used...the first simple example was created as a Windows console application. The project I'm having difficulty with is in a DLL.

我将使用调试器将其附加到DLL,并逐步执行有效的代码,直到在beginthread调用之后到达循环,然后它永远循环并永远不会进入线程.

I'm attaching to the DLL with the debugger and stepping through the code which works until it gets to the loop after the beginthread call then it just loops forever and never gets into the thread.

我刚刚尝试了以下操作,添加了一个带有标准C函数的独立线程:

I just tried the following, adding a standalone thread with a standard C function:

    unsigned __stdcall threadTest(void* pobjData) {
        OutputDebugString("threadTest\n");
        return 0;
   }

然后我如下修改"_beginthread"调用:

I then modify the "_beginthread" call as follows:

    mhThread = (HANDLE)_beginthreadex(0, 0, threadTest, pobjParam, 0, 0);

可悲的是结果是相同的,未调用threadTest函数.但是会返回一个有效的句柄.

Sadly the result is the same, the threadTest function is not called. But a valid handle is returned.

发现了这个

无法调用dll文件中的线程

看起来很有趣,并且可以解释我遇到的奇怪行为.

Looks interesting and may explain the strange behaviour I'm experiencing.

推荐答案

解决了……起初我没有意识到,但是由于某种原因,现有的DLL调用了:

Solved...I didn't realise at first but for some reason the existing DLL had a call to:

    DisableThreadLibraryCalls(hInstance);

这可防止线程运行.对此进行注释后,现在一切正常.

This prevents the threads from running. Having commented this out everything now works.

这篇关于线程未运行,为什么?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆