用类成员函数调用AfxBeginThread?

发布于 2024-12-11 12:20:17 字数 627 浏览 0 评论 0原文

如何使用任意非静态类方法调用 AfxBeginThread?也许我可以用 boost bind 做点什么?以下是 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);

How can I call AfxBeginThread with an arbitrary non-static class method? Maybe there is something I can do with boost bind? Below is the expected usage from Microsoft (and is an example of calling a non-static method but it is hard-coded which method):

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);

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(3

南薇 2024-12-18 12:20:17

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

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

You will need a static function to pass to AfxBeginThread, but it can be a very simple function that calls into the object. Here's an untested template function that might work.

template<class T>
UINT __cdecl StartThread(LPVOID pParam)
{
    return ((T*)pParam)->MyThreadProc();
}
夏末染殇 2024-12-18 12:20:17

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

boost:bind 不会对你有任何帮助... AfxBeginThread 必须是一个 C++ 模板函数,否则它无法与 boost::bind 或带有捕获的 C++11 lambda 兼容。

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

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::thread myFooFooThread( boost::bind( &Foo::Foo, myFooObject ) );

Your code sample is fine. You will need a thread function for each different non-static class method you want to call in separate threads.

boost:bind will not help you whatsoever... AfxBeginThread would have to be a C++ template function, otherwise it cant be compatible with boost::bind or C++11 lambdas with captures.

One Alternative is to create a struct, with an enum for each class/method combination you will have, but this still requires you to manually add code to both the enum and the callback function for each class/method combination. However its not that much less code than creating a separate thread function for each class/method combination.

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 example (untested):

boost::thread myFooFooThread( boost::bind( &Foo::Foo, myFooObject ) );
青丝拂面 2024-12-18 12:20:17

我知道这个问题很老了——但它接近我目前的情况。我正在开发一个用 Visual Studio 2008 项目编写的应用程序,并且希望避免所有启动函数。

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

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

I know this question is pretty old -- but it's close to my current situation. I am working on an application written in Visual Studio 2008 project, and would like to avoid all the start functions.

What I found is there are two different invocations of AfxBeginThread: One requires the start function (for launching working threads); the other takes, as its first parameter a class derived from CWinClass and is used for creating User Interface connected objects AND worker threads.

I am choosing the second option. Would this not also work in the above question?

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文