如何在函数内传递和启动多个线程?
How to pass and start multiple threads within a function?
我想将任意个函数及其参数传递给一个名为startThread
的函数,这样它可以同时 运行 它们。
我的代码如下,但很明显,它有语法错误:
#include <iostream>
#include <thread>
#include <chrono>
#include <vector>
#include <exception>
int test1( int i, double d )
{
// do something...
using namespace std::chrono_literals;
std::this_thread::sleep_for( 3000ms );
return 0;
}
int test2( char c )
{
// do something...
using namespace std::chrono_literals;
std::this_thread::sleep_for( 2000ms );
return 0;
}
template< class Fn, class... Args > // how should I write the template and startThread params to
int startThread( Fn&&... fns, Args&&... args ) // get arbitrary functions as threads and their own arguments?
{
std::vector< std::thread > threads;
threads.push_back( std::thread( test1, 2, 65.2 ) ); // how to automate the task of starting the
threads.push_back( std::thread( test2, 'A' ) ); // threads instead of writing them one by one?
std::cout << "synchronizing all threads...\n";
for ( auto& th : threads ) th.join();
return 0;
}
int main( )
{
int successIndicator { };
try
{
successIndicator = startThread( test1( 2, 65.2 ), test2( 'A' ) ); // what should be passed to startThread?
} // How to pass the arguments?
catch ( const std::exception& e )
{
successIndicator = -1;
std::cerr << e.what( ) << '\n';
}
return successIndicator;
}
提前致谢。
这就是我的做法,使用递归模板函数。
std::async 而不是 std::thread
#include <future>
#include <chrono>
#include <thread>
#include <iostream>
void test1(int /*i*/, double /*d*/)
{
std::cout << "Test1 start\n";
std::this_thread::sleep_for(std::chrono::milliseconds(300));
std::cout << "Test1 done\n";
}
void test2(bool)
{
std::cout << "Test2 start\n";
std::this_thread::sleep_for(std::chrono::milliseconds(500));
std::cout << "Test2 done\n";
}
//-----------------------------------------------------------------------------
// Recursive template function that will start all passed functions
// and then waits for them to be finished one by one.
// this will still be limited by the slowest function
// so no need to store them in a collection or something
template<typename Fn, typename... Fns>
void run_parallel(Fn fn, Fns&&... fns)
{
// I prefer using std::async instead of std::thread
// it has a better abstraction and futures
// allow passing of exceptions back to the calling thread.
auto future = std::async(std::launch::async, fn);
// are there any more functions to start then do so
if constexpr (sizeof...(fns) > 0)
{
run_parallel(std::forward<Fns>(fns)...);
}
future.get();
}
//-----------------------------------------------------------------------------
int main()
{
std::cout << "main start\n";
// start all functions by creating lambdas for them
run_parallel(
[]() { test1(1, 1.10); },
[]() { test2(true); }
);
std::cout << "main done\n";
}
可以把这些函数打包成一个tuple
,然后把每个函数对应的参数打包成一个tuple
,然后一起传入startThread()
,然后展开通过std::apply
实现函数,然后通过std::apply
展开相应的参数传入函数。像这样:
template<class FunTuple, class... ArgsTuple>
int startThread(FunTuple fun_tuple, ArgsTuple... args_tuple) {
std::vector<std::thread> threads;
std::apply([&](auto... fun) {
(threads.emplace_back(
[&] { std::apply([&](auto... args) { fun(args...); }, args_tuple); }
), ...);
}, fun_tuple);
std::cout << "synchronizing all threads...\n";
for (auto& th : threads ) th.join();
return 0;
}
然后你可以这样调用startThread()
:
startThread(std::tuple(test1, test2), std::tuple(2, 65.2), std::tuple('A'));
我想将任意个函数及其参数传递给一个名为startThread
的函数,这样它可以同时 运行 它们。
我的代码如下,但很明显,它有语法错误:
#include <iostream>
#include <thread>
#include <chrono>
#include <vector>
#include <exception>
int test1( int i, double d )
{
// do something...
using namespace std::chrono_literals;
std::this_thread::sleep_for( 3000ms );
return 0;
}
int test2( char c )
{
// do something...
using namespace std::chrono_literals;
std::this_thread::sleep_for( 2000ms );
return 0;
}
template< class Fn, class... Args > // how should I write the template and startThread params to
int startThread( Fn&&... fns, Args&&... args ) // get arbitrary functions as threads and their own arguments?
{
std::vector< std::thread > threads;
threads.push_back( std::thread( test1, 2, 65.2 ) ); // how to automate the task of starting the
threads.push_back( std::thread( test2, 'A' ) ); // threads instead of writing them one by one?
std::cout << "synchronizing all threads...\n";
for ( auto& th : threads ) th.join();
return 0;
}
int main( )
{
int successIndicator { };
try
{
successIndicator = startThread( test1( 2, 65.2 ), test2( 'A' ) ); // what should be passed to startThread?
} // How to pass the arguments?
catch ( const std::exception& e )
{
successIndicator = -1;
std::cerr << e.what( ) << '\n';
}
return successIndicator;
}
提前致谢。
这就是我的做法,使用递归模板函数。 std::async 而不是 std::thread
#include <future>
#include <chrono>
#include <thread>
#include <iostream>
void test1(int /*i*/, double /*d*/)
{
std::cout << "Test1 start\n";
std::this_thread::sleep_for(std::chrono::milliseconds(300));
std::cout << "Test1 done\n";
}
void test2(bool)
{
std::cout << "Test2 start\n";
std::this_thread::sleep_for(std::chrono::milliseconds(500));
std::cout << "Test2 done\n";
}
//-----------------------------------------------------------------------------
// Recursive template function that will start all passed functions
// and then waits for them to be finished one by one.
// this will still be limited by the slowest function
// so no need to store them in a collection or something
template<typename Fn, typename... Fns>
void run_parallel(Fn fn, Fns&&... fns)
{
// I prefer using std::async instead of std::thread
// it has a better abstraction and futures
// allow passing of exceptions back to the calling thread.
auto future = std::async(std::launch::async, fn);
// are there any more functions to start then do so
if constexpr (sizeof...(fns) > 0)
{
run_parallel(std::forward<Fns>(fns)...);
}
future.get();
}
//-----------------------------------------------------------------------------
int main()
{
std::cout << "main start\n";
// start all functions by creating lambdas for them
run_parallel(
[]() { test1(1, 1.10); },
[]() { test2(true); }
);
std::cout << "main done\n";
}
可以把这些函数打包成一个tuple
,然后把每个函数对应的参数打包成一个tuple
,然后一起传入startThread()
,然后展开通过std::apply
实现函数,然后通过std::apply
展开相应的参数传入函数。像这样:
template<class FunTuple, class... ArgsTuple>
int startThread(FunTuple fun_tuple, ArgsTuple... args_tuple) {
std::vector<std::thread> threads;
std::apply([&](auto... fun) {
(threads.emplace_back(
[&] { std::apply([&](auto... args) { fun(args...); }, args_tuple); }
), ...);
}, fun_tuple);
std::cout << "synchronizing all threads...\n";
for (auto& th : threads ) th.join();
return 0;
}
然后你可以这样调用startThread()
:
startThread(std::tuple(test1, test2), std::tuple(2, 65.2), std::tuple('A'));