首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >使用CreateThread执行lambda

使用CreateThread执行lambda
EN

Stack Overflow用户
提问于 2022-09-08 08:33:21
回答 3查看 148关注 0票数 2

是否有更好的方法来使用CreateThread,而不是每次都为lpParameter的唯一目的创建一个空闲函数?

对于创建持久线程,有什么现代的CreateThread替代方案吗?

编辑:也许您应该使用std::async(lambda)。我想它只是用CreateThread实现的。也许这个问题的答案是查找std::async是如何实现的(假设它是一个库特性)。

代码语言:javascript
复制
DWORD WINAPI MyThreadFunction(
  _In_ LPVOID lpParameter
)
{
    ((MyClass*)lpParameter)->RunLoop();
}

void MyClass::LaunchThread()
{
    CreateThread( 
            NULL,                   // default security attributes
            0,                      // use default stack size  
            MyThreadFunction,       // thread function name
            this,          // argument to thread function 
            0,                      // use default creation flags 
            NULL);   // returns the thread identifier 
}
EN

回答 3

Stack Overflow用户

回答已采纳

发布于 2022-09-08 09:12:00

有几种实现并行的机制(如上面提到的std::async等)。

但是最类似于使用CreateThread的原始代码的现代代码是。它可以使用全局函数、lambda类方法(这似乎最适合您)构建:

代码语言:javascript
复制
m_thread = std::thread([this](){ RunLoop(); });  // pass a lambda

代码语言:javascript
复制
m_thread = std::thread(&MyClass::RunLoop, this); // pass a method

请注意,std::thread在构造时开始运行(可能)。还要注意,std::async并不保证它将在单独的线程上运行,即使它运行在一个线程上,它也可能是一个池中的线程。这种行为可能与最初的CreateThread不一样。

下面是使用std::thread (包括取消)的完整示例:

代码语言:javascript
复制
#include <thread>
#include <chrono>
#include <atomic>
#include <iostream>

class MyClass
{
public:
    MyClass()  {}
    ~MyClass() { EndThread(); }

    void LaunchThread()
    {
        EndThread();    // in case it was already running
        m_bThreadShouldExit = false;
        // Start the thread with a class method:
        m_thread = std::thread(&MyClass::RunLoop, this);
    }

    void EndThread()
    {
        // Singal the thread to exit, and wait for it:
        m_bThreadShouldExit = true;
        if (m_thread.joinable())
        {
            m_thread.join();
        }
    }

    void RunLoop()
    {
        std::cout << "RunLoop started" << std::endl;
        while (!m_bThreadShouldExit)
        {
            std::cout << "RunLoop doing something ..." << std::endl;
            std::this_thread::sleep_for(std::chrono::milliseconds(1000));
        }
        std::cout << "RunLoop ended" << std::endl;
    }

private:
    std::thread         m_thread;
    std::atomic_bool    m_bThreadShouldExit{ false };
};


int main()
{
    MyClass m;
    m.LaunchThread();
    std::this_thread::sleep_for(std::chrono::milliseconds(5000));
    m.EndThread();
}

可能的输出:

代码语言:javascript
复制
RunLoop started
RunLoop doing something ...
RunLoop doing something ...
RunLoop doing something ...
RunLoop doing something ...
RunLoop doing something ...
RunLoop ended
票数 1
EN

Stack Overflow用户

发布于 2022-09-08 09:00:16

我查看了std::async的MSVC实现,他们使用直接接受可调用对象的::Concurrency::create_task实现了它。

https://learn.microsoft.com/en-us/cpp/parallel/concrt/task-parallelism-concurrency-runtime

我还研究了它们对create_task的实现。

代码语言:javascript
复制
template<typename _Ty>
__declspec(noinline) // Ask for no inlining so that the _CAPTURE_CALLSTACK gives us the expected result
explicit task(_Ty _Param)
{
    task_options _TaskOptions;
    details::_ValidateTaskConstructorArgs<_ReturnType,_Ty>(_Param);

    _CreateImpl(_TaskOptions.get_cancellation_token()._GetImplValue(), _TaskOptions.get_scheduler());
    // Do not move the next line out of this function. It is important that _CAPTURE_CALLSTACK() evaluates to the call site of the task constructor.
    _SetTaskCreationCallstack(_CAPTURE_CALLSTACK());

    _TaskInitMaybeFunctor(_Param, decltype(details::_IsCallable(_Param,0))());
}

因此,在新线程上启动lambda非常困难,超出了这个问题的范围。

票数 0
EN

Stack Overflow用户

发布于 2022-09-08 09:09:30

std::std()和std::(,)很可能是像刚才那样在内部实现的,唯一的例外是没有捕获的lambdas 可以被隐式转换为函数指针,这些指针几乎可以直接用nullptr lpParameter传递到CreateThread函数。具有捕获列表的Lambdas几乎是语法糖,但在内部,它们被翻译成这样的东西(非常简化):

代码语言:javascript
复制
struct <internal_lambda_name>
{
    <capture list...> fields...;

    void operator()(<arguments...>){<code...>;}
};

因此,它们基本上转换为struct类型的对象,因此它们需要某种方式来存储所有这些捕获,为了在具有CreateThread函数的其他线程上执行,它们需要某种方式来确保它们中存储的捕获列表数据在执行过程中可用。

票数 0
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/73645987

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档