C++ 单独线程执行带输入值和返回值的函数

C++ 单独线程执行函数

  • C++ 单独线程执行带输入值和返回值的函数
  • C++ 单独线程执行带输入值和返回值的类方法函数

1. C++ 单独线程执行带输入值和返回值的函数

  • 在 C++ 中创建单独线程执行带输入值和返回值的函数,有几种常见方法。以下是几种实现方式:

  • 方法一:使用 std::promise 和 std::future(推荐)

#include <iostream>
#include <thread>
#include <future>
#include <functional>

// 示例函数:计算平方
int square(int x) {
    return x * x;
}

// 使用 promise 和 future 的线程函数
void thread_function(std::promise<int>&& promise, int value) {
    try {
        int result = square(value);
        promise.set_value(result); // 设置结果
    } catch (...) {
        promise.set_exception(std::current_exception()); // 处理异常
    }
}

int main() {
    int input = 5;
    
    // 创建 promise 和 future
    std::promise<int> promise;
    std::future<int> future = promise.get_future();
    
    // 创建线程并传递 promise
    std::thread t(thread_function, std::move(promise), input);
    
    // 获取结果(会阻塞直到结果可用)
    int result = future.get();
    
    std::cout << "Square of " << input << " is " << result << std::endl;
    
    t.join();
    return 0;
}
  • 方法二:使用 std::packaged_task
#include <iostream>
#include <thread>
#include <future>

int multiply(int a, int b)
{
    return a * b;
}

int main() {
    int a = 6, b = 7;
    
    // 创建 packaged_task
    std::packaged_task<int(int, int)> task(multiply);
    std::future<int> future = task.get_future();
    
    // 创建线程并执行任务
    std::thread t(std::move(task), a, b);
    
    // 获取结果
    int result = future.get();
    std::cout << a << " * " << b << " = " << result << std::endl;
    
    t.join();
    return 0;
}
  • 方法三:使用 std::async(最简单)
#include <iostream>
#include <future>

double calculate_circle_area(double radius) {
    return 3.14159 * radius * radius;
}

int main() {
    double radius = 5.0;
    
    // 使用 async 异步执行函数
    std::future<double> future = std::async(
        std::launch::async, // 明确指定异步执行
        calculate_circle_area, 
        radius
    );
    
    // 在主线程做其他工作...
    std::cout << "Calculating area in background..." << std::endl;
    
    // 获取结果(如果需要)
    double area = future.get();
    std::cout << "Area of circle with radius " << radius 
              << " is " << area << std::endl;
    
    return 0;
}
  • 方法四:使用 Lambda 表达式和 promise
#include <iostream>
#include <thread>
#include <future>

int main() {
    int base = 2, exponent = 10;
    
    std::promise<int> promise;
    std::future<int> future = promise.get_future();
    
    // 使用 lambda 表达式创建线程
    std::thread t([&promise, base, exponent]() {
        int result = 1;
        for (int i = 0; i < exponent; ++i) {
            result *= base;
        }
        promise.set_value(result);
    });
    
    // 分离线程或继续其他工作
    t.detach();
    
    // 在需要时获取结果
    int power_result = future.get();
    std::cout << base << "^" << exponent << " = " << power_result << std::endl;
    
    return 0;
}
  • 方法五:封装成可重用的线程类
#include <iostream>
#include <thread>
#include <future>
#include <functional>

template<typename F, typename... Args>
class ThreadWithResult {
private:
    std::thread thread;
    std::future<std::invoke_result_t<F, Args...>> future;
    
public:
    ThreadWithResult(F&& func, Args&&... args) {
        std::packaged_task<std::invoke_result_t<F, Args...>()> task(
            [func = std::forward<F>(func), 
             args = std::make_tuple(std::forward<Args>(args)...)]() mutable {
                return std::apply(func, std::move(args));
            }
        );
        
        future = task.get_future();
        thread = std::thread(std::move(task));
    }
    
    auto get() {
        return future.get();
    }
    
    void join() {
        if (thread.joinable()) {
            thread.join();
        }
    }
    
    ~ThreadWithResult() {
        join();
    }
};

// 使用示例
int add(int a, int b) {
    return a + b;
}

int main() {
    ThreadWithResult thread_obj(add, 10, 20);
    
    int result = thread_obj.get();
    std::cout << "Result: " << result << std::endl;
    
    return 0;
}

总结

  • std::async - 最简单,适合大多数情况

  • std::packaged_task - 灵活,可以控制线程创建

  • std::promise/std::future - 最底层,完全控制

  • 自定义线程类 - 可重用,封装性好

  • 根据你的具体需求选择合适的方法。对于简单的异步任务,推荐使用 std::async;需要更多控制时,使用 std::packaged_task 或 std::promise。

2. C++ 单独线程执行带输入值和返回值的类方法函数

在 C++ 中创建单独线程执行带输入值和返回值的类方法函数,有几种常见方法。以下是详细的实现方式:

  • 方法一:使用 std::promise 和 std::future(推荐)
#include <iostream>
#include <thread>
#include <future>
#include <functional>

class Calculator {
public:
    int add(int a, int b) {
        std::this_thread::sleep_for(std::chrono::milliseconds(100)); // 模拟耗时操作
        return a + b;
    }
    
    double multiply(double a, double b) {
        return a * b;
    }
    
    std::string concatenate(const std::string& a, const std::string& b) {
        return a + b;
    }
};

// 包装类方法的线程函数模板
template<typename Class, typename Result, typename... Args>
void member_function_wrapper(
    std::promise<Result>&& promise, 
    Class* obj, 
    Result (Class::*method)(Args...), 
    Args... args) {
    try {
        Result result = (obj->*method)(args...);
        promise.set_value(result);
    } catch (...) {
        promise.set_exception(std::current_exception());
    }
}

int main() {
    Calculator calc;
    
    // 执行 add 方法
    std::promise<int> promise1;
    std::future<int> future1 = promise1.get_future();
    
    std::thread t1(member_function_wrapper<Calculator, int, int, int>,
                  std::move(promise1), &calc, &Calculator::add, 10, 20);
    
    int add_result = future1.get();
    std::cout << "Add result: " << add_result << std::endl;
    t1.join();
    
    // 执行 multiply 方法
    std::promise<double> promise2;
    std::future<double> future2 = promise2.get_future();
    
    std::thread t2(member_function_wrapper<Calculator, double, double, double>,
                  std::move(promise2), &calc, &Calculator::multiply, 3.5, 2.0);
    
    double multiply_result = future2.get();
    std::cout << "Multiply result: " << multiply_result << std::endl;
    t2.join();
    
    return 0;
}

方法二:使用 Lambda 表达式和 std::promise

#include <iostream>
#include <thread>
#include <future>

class DataProcessor {
private:
    int processing_factor;
    
public:
    DataProcessor(int factor) : processing_factor(factor) {}
    
    int process_data(int data) {
        std::this_thread::sleep_for(std::chrono::milliseconds(200));
        return data * processing_factor;
    }
    
    std::string format_result(int result, const std::string& prefix) {
        return prefix + ": " + std::to_string(result);
    }
};

int main() {
    DataProcessor processor(5);
    
    // 使用 lambda 包装类方法
    std::promise<int> promise;
    std::future<int> future = promise.get_future();
    
    int input_data = 42;
    
    std::thread t([&processor, &promise, input_data]() {
        try {
            int result = processor.process_data(input_data);
            promise.set_value(result);
        } catch (...) {
            promise.set_exception(std::current_exception());
        }
    });
    
    int processed_result = future.get();
    std::cout << "Processed result: " << processed_result << std::endl;
    
    // 另一个例子:带多个参数的方法
    std::promise<std::string> promise2;
    std::future<std::string> future2 = promise2.get_future();
    
    std::thread t2([&processor, &promise2, processed_result]() {
        try {
            std::string formatted = processor.format_result(processed_result, "Result");
            promise2.set_value(formatted);
        } catch (...) {
            promise2.set_exception(std::current_exception());
        }
    });
    
    std::string formatted_result = future2.get();
    std::cout << formatted_result << std::endl;
    
    t.join();
    t2.join();
    
    return 0;
}
  • 方法三:使用 std::packaged_task
#include <iostream>
#include <thread>
#include <future>
#include <functional>

class MathOperations {
public:
    double power(double base, int exponent) {
        double result = 1.0;
        for (int i = 0; i < exponent; ++i) {
            result *= base;
        }
        return result;
    }
    
    int factorial(int n) {
        if (n <= 1) return 1;
        return n * factorial(n - 1);
    }
};

int main() {
    MathOperations math;
    
    // 使用 packaged_task 包装类方法
    std::packaged_task<double(MathOperations*, double, int)> task1(
        [](MathOperations* obj, double base, int exponent) {
            return obj->power(base, exponent);
        }
    );
    
    std::future<double> future1 = task1.get_future();
    std::thread t1(std::move(task1), &math, 2.0, 8);
    
    double power_result = future1.get();
    std::cout << "2.0^8 = " << power_result << std::endl;
    t1.join();
    
    // 另一个例子
    std::packaged_task<int(MathOperations*, int)> task2(
        [](MathOperations* obj, int n) {
            return obj->factorial(n);
        }
    );
    
    std::future<int> future2 = task2.get_future();
    std::thread t2(std::move(task2), &math, 5);
    
    int factorial_result = future2.get();
    std::cout << "5! = " << factorial_result << std::endl;
    t2.join();
    
    return 0;
}
  • 方法四:使用 std::bind 和 std::async
#include <iostream>
#include <future>
#include <functional>

class FileProcessor {
public:
    std::string read_and_process(const std::string& filename, int chunk_size) {
        // 模拟文件处理
        std::this_thread::sleep_for(std::chrono::milliseconds(300));
        return "Processed: " + filename + " (chunk: " + std::to_string(chunk_size) + ")";
    }
    
    int count_lines(const std::string& content) {
        int count = 0;
        for (char c : content) {
            if (c == '\n') count++;
        }
        return count;
    }
};

int main() {
    FileProcessor processor;
    
    // 使用 std::bind 绑定对象和方法
    auto bound_func = std::bind(&FileProcessor::read_and_process, 
                               &processor, 
                               "data.txt", 
                               1024);
    
    // 使用 async 异步执行
    std::future<std::string> future = std::async(std::launch::async, bound_func);
    
    // 主线程可以继续工作
    std::cout << "Processing file in background..." << std::endl;
    
    // 获取结果
    std::string result = future.get();
    std::cout << result << std::endl;
    
    // 另一个例子:使用 lambda 包装
    std::future<int> line_count_future = std::async(std::launch::async, 
        [&processor, result]() {
            return processor.count_lines(result);
        }
    );
    
    int line_count = line_count_future.get();
    std::cout << "Line count: " << line_count << std::endl;
    
    return 0;
}
  • 方法五:封装成可重用的线程类
#include <iostream>
#include <thread>
#include <future>
#include <functional>
#include <memory>

template<typename Class, typename Result, typename... Args>
class MemberFunctionThread {
private:
    std::thread thread;
    std::future<Result> future;
    std::promise<Result> promise;
    
public:
    MemberFunctionThread(Class* obj, Result (Class::*method)(Args...), Args... args) {
        future = promise.get_future();
        
        thread = std::thread([this, obj, method, args...]() {
            try {
                Result result = (obj->*method)(args...);
                promise.set_value(result);
            } catch (...) {
                promise.set_exception(std::current_exception());
            }
        });
    }
    
    Result get() {
        return future.get();
    }
    
    void join() {
        if (thread.joinable()) {
            thread.join();
        }
    }
    
    ~MemberFunctionThread() {
        join();
    }
};

// 使用示例
class Worker {
public:
    int heavy_computation(int x, int y) {
        std::this_thread::sleep_for(std::chrono::milliseconds(500));
        return x * y + x + y;
    }
    
    std::string generate_report(int data, const std::string& title) {
        return title + " Report: " + std::to_string(data);
    }
};

int main() {
    Worker worker;
    
    // 创建线程执行类方法
    MemberFunctionThread<Worker, int, int, int> thread1(
        &worker, &Worker::heavy_computation, 10, 20
    );
    
    int computation_result = thread1.get();
    std::cout << "Computation result: " << computation_result << std::endl;
    
    // 另一个线程
    MemberFunctionThread<Worker, std::string, int, std::string> thread2(
        &worker, &Worker::generate_report, computation_result, "Final"
    );
    
    std::string report = thread2.get();
    std::cout << report << std::endl;
    
    return 0;
}
  • 方法六:使用 std::invoke(C++17)
#include <iostream>
#include <thread>
#include <future>
#include <functional>

class NetworkService {
public:
    std::string fetch_data(const std::string& url, int timeout) {
        std::this_thread::sleep_for(std::chrono::milliseconds(400));
        return "Data from " + url + " (timeout: " + std::to_string(timeout) + "ms)";
    }
    
    int parse_response(const std::string& response) {
        return response.length();
    }
};

int main() {
    NetworkService service;
    
    // 使用 std::invoke 调用类方法
    std::packaged_task<std::string()> task(
        [&service]() -> std::string {
            return std::invoke(&NetworkService::fetch_data, &service, "https://example.com", 5000);
        }
    );
    
    std::future<std::string> future = task.get_future();
    std::thread t(std::move(task));
    
    std::string data = future.get();
    std::cout << "Fetched: " << data << std::endl;
    
    t.join();
    
    return 0;
}

总结

Lambda + promise - 最灵活,适合简单场景

std::packaged_task - 代码清晰,易于理解

std::async + std::bind - 简洁,适合快速开发

封装线程类 - 可重用,适合复杂项目

std::invoke - 现代 C++ 风格,类型安全

选择方法时考虑:

代码简洁性:使用 std::async 或 lambda

性能控制:使用 std::thread 和 std::promise

代码重用:封装成线程类

现代性:使用 std::invoke(C++17+)
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

明月醉窗台

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值