Как вызывать методы класса в фоновом потоке с помощью CThreadPool

#c #visual-studio #winapi #threadpool #atl

#c #visual-studio #winapi #threadpool #atl

Вопрос:

Допустим, у вас есть какой-то класс, и вы хотите вызвать некоторые из его методов в фоновом потоке. Это то, что меня интересует, и я подумал CThreadPool , что было бы неплохо использовать для этого. Мне было интересно, использовал ли кто CThreadPool -нибудь раньше вызовы методов for.

Итак, вот что я настроил. На основе этого примера от Microsoft я создал абстрактный класс «task» (который я обозначил как интерфейс), а также рабочий класс:

 class ITask
{
public:
    virtual void DoTask(LPVOID, LPOVERLAPPED) = 0;
};

class CWorker
{
public:
    typedef DWORD_PTR RequestType;

    BOOL Initialize(LPVOID)
    {
        return TRUE;
    }

    void Execute(RequestType dw, LPVOID pvParam, LPOVERLAPPED pOverlapped) throw()
    {
        ITask* pTask = (ITask*)(DWORD_PTR)dw;
        pTask->DoTask(pvParam, pOverlapped);
    }

    void Terminate(LPVOID)
    {
    }
};
 

Затем в моем основном классе я, по сути, делаю это:

 class MyClass
{
public:
    MyClass()
    {
        m_threadpool.Initialize(this, NUM_OF_THREADS_DESIRED);
    }
    ~MyClass()
    {
        m_threadpool.Shutdown();
    }

private:
    CThreadPool<CWorker> m_threadpool;
    
    class : public ITask
    {
    public:
        void DoTask(LPVOID pvParam, LPOVERLAPPED)
        {
            MyClass* pObj = (MyClass*)pvParam;
            pObj->MethodToCallOnBackgroundThread();
        }
    } m_task;

    void MethodForQueuing()
    {
        m_threadpool.QueueRequest((CWorker::RequestType)amp;m_task);
    }

    void MethodToCallOnBackgroundThread()
    {
        // Do something
    }
};
 

Кажется, это работает. Одним из недостатков является то ITask , что для каждого метода, для которого вы хотели бы использовать threadpool, требуется объявление нового производного класса, но, по-видимому, так работает пример Microsoft. Я предполагаю, что другим подходом было бы создать более общий объект task, а затем передать перечисление или что-то в этом роде, которое можно использовать для оператора switch в методе класса. В любом случае, кто-нибудь сталкивался с этой ситуацией, и если да, есть ли у вас какие-либо данные?

Комментарии:

1. Если нет конкретной причины, по которой вы хотите написать такой код начала 2000-х годов излишне специфичным для платформы способом, я бы посоветовал вам либо просто использовать std::async , либо, по крайней мере, упаковывать свои задачи в std::function объекты вместо того, чтобы писать каждый конкретный подкласс вручную.

2. Хорошо, спасибо. Я проверю это. Это в контексте проекта ATL, поэтому я и рассматривал CThreadPool .

3. использовать использовать системный пул и QueueUserWorkItem или CreateThreadpoolWork