代码改变世界

ATL 线程池的使用

2011-07-16 20:45  Clingingboy  阅读(2357)  评论(0编辑  收藏  举报

 

一.自定义一个Worker

class CMyWorker
  {
  public:
     typedef MyRequestType RequestType;
  
     BOOL Initialize(void* pvWorkerParam);
  
     void Execute(MyRequestType request, void* pvWorkerParam, OVERLAPPED* pOverlapped);
  
     void Terminate(void* pvWorkerParam);
  };

必须实现以上接口

具体参考如下:

http://msdn.microsoft.com/zh-cn/library/ytkt93h8.aspx

Demo:

LONG g_lCurrId = -1;

class CMyWorker
{
public:
    typedef DWORD_PTR RequestType;

    CMyWorker() : m_dwExecs( 0 )
    {
        m_lId = InterlockedIncrement( &g_lCurrId );
    }

    virtual BOOL Initialize(void *pvParam)
    {
        printf("[%d]: CMyWorker.Initialize(%d)\n", (DWORD_PTR)::GetCurrentThreadId(), (DWORD_PTR)pvParam );
        return TRUE;
    }

    virtual void Terminate(void* /*pvParam*/)
    {
        printf( "CMyWorker #%d exec'd %d times.\n", m_lId, m_dwExecs );
    }

    void Execute(RequestType dw, void *pvParam, OVERLAPPED* pOverlapped) throw()
    {
        ATLASSERT(pvParam != NULL);

        printf("[%d] CMyWorker::Execute(dw=%d, pvParam=%d, pOverlapped=%d\n", 
            ::GetCurrentThreadId(), dw, (DWORD_PTR)pvParam, (DWORD_PTR)pOverlapped);

        CTaskBase* pTask = (CTaskBase*)(DWORD_PTR)dw;
        pTask->DoTask(pvParam, pOverlapped);

        m_dwExecs++;
    }

    virtual BOOL GetWorkerData(DWORD /*dwParam*/, void ** /*ppvData*/)
    {
        return FALSE;
    }

protected:
    DWORD    m_dwExecs;
    LONG    m_lId;
}; // CMyWorker

二.线程池(CThreadPool)

#define THREADPOOL_SIZE    5

///////////////////////////////////////////////////////////////////////////////
int main(int /*argc*/, char* /*argv[]*/)
{
    CThreadPool<CMyWorker> pool;
    CTaskArray    tasks;

    HRESULT hr = pool.Initialize((void*)321, THREADPOOL_SIZE);
    
    if( SUCCEEDED( hr ) ) {
        int i = -1;
        CTaskBase* pTask = NULL;
        if ( CreateTasks(tasks, 100) ) {
            for ( i = 0; i < tasks.GetSize(); i++ ) {
                pTask = tasks[ i ];
                ATLASSERT( NULL != pTask );
                pool.QueueRequest( (CMyWorker::RequestType) pTask );
            }
        }

        // Allow a little time for all the tasks to complete
        Sleep(1000);

        // Clean up the tasks and shutdown the thread pool
        for ( i = 0; i < tasks.GetSize(); i++ ) {
            pTask = tasks[ i ];
            ATLASSERT( NULL != pTask );
            delete pTask;
        }

        // Shutdown the thread pool
        pool.Shutdown();
    }
    else
        printf("Failed to init thread pool!");

    printf("\n");
    return 0;
}

参考:http://msdn.microsoft.com/zh-cn/library/dta23y51.aspx

  1. Initialize初始化线程数量,并初始化Worker
  2. QueueRequest则调用Worker的Execute方法
  3. 等Worker全部执行完毕以后才调用Terminate方法

三.IThreadPoolConfig

定义了一个基础的接口

// Used to configure the worker thread pool. This can be used by any
// client of the CThreadPool class.
__interface __declspec(uuid("B1F64757-6E88-4fa2-8886-7848B0D7E660"))
    IThreadPoolConfig : public IUnknown
{
    STDMETHOD(SetSize)(_In_ int nNumThreads);
    STDMETHOD(GetSize)(_Out_ int *pnNumThreads);
    STDMETHOD(SetTimeout)(_In_ DWORD dwMaxWait);
    STDMETHOD(GetTimeout)(_Out_ DWORD *pdwMaxWait);
};

四.ThreadTraits

分两种CRTThreadTraits和Win32ThreadTraits,分别调用_beginthreadex和CreateThread方法

五.WaitTraits

只实现了Win32WaitTraits了,即调用了WaitForSingleObject