是否有更好的方法来使用CreateThread,而不是每次都为lpParameter的唯一目的创建一个空闲函数?
对于创建持久线程,有什么现代的CreateThread替代方案吗?
编辑:也许您应该使用std::async(lambda)。我想它只是用CreateThread实现的。也许这个问题的答案是查找std::async是如何实现的(假设它是一个库特性)。
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
}发布于 2022-09-08 09:12:00
有几种实现并行的机制(如上面提到的std::async等)。
但是最类似于使用CreateThread的原始代码的现代代码是。它可以使用全局函数、、lambda或类方法(这似乎最适合您)构建:
m_thread = std::thread([this](){ RunLoop(); }); // pass a lambda或
m_thread = std::thread(&MyClass::RunLoop, this); // pass a method请注意,std::thread在构造时开始运行(可能)。还要注意,std::async并不保证它将在单独的线程上运行,即使它运行在一个线程上,它也可能是一个池中的线程。这种行为可能与最初的CreateThread不一样。
下面是使用std::thread (包括取消)的完整示例:
#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();
}可能的输出:
RunLoop started
RunLoop doing something ...
RunLoop doing something ...
RunLoop doing something ...
RunLoop doing something ...
RunLoop doing something ...
RunLoop ended发布于 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的实现。
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非常困难,超出了这个问题的范围。
发布于 2022-09-08 09:09:30
std::std()和std::(,)很可能是像刚才那样在内部实现的,唯一的例外是没有捕获的lambdas 可以被隐式转换为函数指针,这些指针几乎可以直接用nullptr lpParameter传递到CreateThread函数。具有捕获列表的Lambdas几乎是语法糖,但在内部,它们被翻译成这样的东西(非常简化):
struct <internal_lambda_name>
{
<capture list...> fields...;
void operator()(<arguments...>){<code...>;}
};因此,它们基本上转换为struct类型的对象,因此它们需要某种方式来存储所有这些捕获,为了在具有CreateThread函数的其他线程上执行,它们需要某种方式来确保它们中存储的捕获列表数据在执行过程中可用。
https://stackoverflow.com/questions/73645987
复制相似问题