用类成员函数调用AfxBeginThread

Call AfxBeginThread with class member function?

本文关键字:AfxBeginThread 函数调用 成员      更新时间:2023-10-16

如何使用任意非静态类方法调用AfxBeginThread ?也许我能对强化绑定做点什么?下面是来自Microsoft的预期用法(并且是调用非静态方法的一个示例,但它是硬编码的方法):

UINT MyThreadProc( LPVOID pParam )
{
    CMyObject* pObject = (CMyObject*)pParam;
    if (pObject == NULL ||
        !pObject->IsKindOf(RUNTIME_CLASS(CMyObject)))
    return 1;   // if pObject is not valid
    // do something with 'pObject'
    return 0;   // thread completed successfully
}
// inside a different function in the program
...
pNewObject = new CMyObject;
AfxBeginThread(MyThreadProc, pNewObject);

您将需要一个静态函数传递给AfxBeginThread,但它可以是一个非常简单的函数,调用到对象中。下面是一个未经测试的模板函数,它可能可以工作。

template<class T>
UINT __cdecl StartThread(LPVOID pParam)
{
    return ((T*)pParam)->MyThreadProc();
}

您的代码示例很好。对于你想在单独的线程中调用的每个不同的非静态类方法,你都需要一个线程函数。

boost:bind将不会帮助你…AfxBeginThread必须是c++模板函数,否则它不能与boost::bind或c++ 11 lambda with capture兼容。

另一种方法是创建一个结构体,为每个类/方法组合创建一个枚举,但这仍然需要您手动为每个类/方法组合添加枚举和回调函数的代码。然而,这并不比为每个类/方法组合创建一个单独的线程函数少得多。

struct ThreadData
{
  LPVOID object;
  enum ObjectCallType {
    Foo_Foo,
    Foo_Bar
  } objectCallType;
  LPVOID* param;
  ThreadData( LPVOID pobject, ObjectCallType poct, LPVOID* pparam=0 )
  :object(pobject), objectCallType(poct), param(pparam) {}
};
UINT MyThreadProc( LPVOID pParam )
{
    TheadData* thData = (ThreadData*)pParam;
    try 
    {
        switch( thData->objectCallType )
        {
            case ThreadData::Foo_Foo:
                Foo* foo = (Foo*)thData->object;
                foo->foo();
                break;
            case ThreadData::Foo_Bar:
                Foo* foo = (Foo*)thData->object;
                foo->bar( thData->param );
                break;
            default:
                throw std::exception("unhandled method call type");
        }
    }
    catch( std::exception& e )
    {
        std::cerr << e.what() << std::endl;
        delete thData;
        return 1;
    }
    delete thData;
    return 0;
}

//usage:
AfxBeginThread(MyThreadProc, new ThreadData(myFooObject,ThreadData::Foo_Bar,myFooCallParam));

Boost示例(未测试):

boost::thread myFooFooThread( boost::bind( &Foo::Foo, myFooObject ) );

我知道这个问题很老了,但它和我现在的情况很接近。我正在Visual Studio 2008项目中编写一个应用程序,并希望避免所有的启动功能。

我发现有两个不同的调用AfxBeginThread:一个需要启动函数(启动工作线程);另一个以cwclass派生的类作为第一个参数,用于创建用户界面连接对象和工作线程。

我选择第二个选项。这在上面的问题中不也适用吗?