Tôi đang sử dụng vc2011 và nó chỉ ra std :: async (std :: launch :: async, ...) là một chút lỗi (đôi khi nó không sinh ra các luồng mới và chạy chúng song song, nhưng thay vào đó reuses chủ đề và chạy nhiệm vụ cái khác). Điều này quá chậm khi tôi thực hiện các cuộc gọi mạng tốn kém. Vì vậy, tôi figured tôi muốn viết chức năng async của riêng tôi. Tôi đang gặp khó khăn mặc dù, nơi nên std :: lời hứa sống? Trong 1) chức năng chủ đề, 2) chức năng async, hoặc 3) chức năng người gọi.Thay thế std :: async với phiên bản của riêng mình nhưng nên std :: lời hứa sống ở đâu?
Code:
#include <future>
#include <thread>
#include <iostream>
#include <string>
#include <vector>
std::string thFun() {
throw std::exception("bang!");
return "val";
}
std::future<std::string> myasync(std::promise<std::string>& prms) {
//std::future<std::string> myasync() {
//std::promise<std::string> prms; //needs to outlive thread. How?
std::future<std::string> fut = prms.get_future();
std::thread th([&](){
//std::promise<std::string> prms; //need to return a future before...
try {
std::string val = thFun();
prms.set_value(val);
} catch(...) {
prms.set_exception(std::current_exception());
}
});
th.detach();
return fut;
}
int main() {
std::promise<std::string> prms; //I really want the promise hidden iway in the myasync func and not live here in caller code but the promise needs to outlive myasync and live as long as the thread. How do I do this?
auto fut = myasync(prms);
//auto fut = myasync(); //Exception: future already retrieved
try {
auto res = fut.get();
std::cout << "Result: " << res << std::endl;
} catch(const std::exception& exc) {
std::cout << "Exception: " << exc.what() << std::endl;
}
}
I cant dường như vượt qua một thực tế là std :: hứa cần phải sống lâu hơn chức năng async (và sống lâu như sợi chỉ), do đó không thể hứa sống như một biến cục bộ trong func async. Nhưng std :: promise cũng không nên tồn tại trong mã người gọi, vì người gọi chỉ cần biết về tương lai. Và tôi không biết làm thế nào để làm cho lời hứa sống trong chức năng thread như async cần phải trả lại một tương lai trước khi nó thậm chí còn gọi func thread. Tôi đang gãi đầu vào cái này.
Bất kỳ ai có ý tưởng nào?
Chỉnh sửa: Tôi đang làm nổi bật điều này ở đây vì nhận xét hàng đầu có một chút sai lệch. Trong khi mặc định cho std :: asycn được cho phép là chế độ dererred, khi một chính sách khởi động của std :: launch :: async được thiết lập rõ ràng nó phải hoạt động "như thể" các luồng được sinh ra và chạy cùng một lúc (xem wording trong vi .cppreference.com/w/cpp/thread/async). Xem ví dụ trong pastebin.com/5dWCjjNY cho một trường hợp mà đây không phải là hành vi được nhìn thấy trong vs20011. Giải pháp hoạt động tốt và tăng tốc ứng dụng thế giới thực của tôi theo hệ số 10.
Chỉnh sửa 2: MS sửa lỗi. Xem thêm thông tin ở đây: https://connect.microsoft.com/VisualStudio/feedback/details/735731/std-async-std-launch-async-does-not-behave-as-std-thread
"đôi khi nó không sinh ra chủ đề mới và chạy chúng song song, nhưng thay vì sử dụng lại chủ đề và chạy tác vụ cái khác" Đó không phải là lỗi; đó là cách nó được phép làm việc. Không có sự đảm bảo nào trong đặc tả rằng bất kỳ cuộc gọi async cụ thể nào sẽ chạy trong một luồng khác từ các cuộc gọi không đồng bộ trước hoặc trong tương lai.Nếu bạn muốn điều đó, sau đó chỉ cần tạo một loạt các chủ đề, dính chúng vào một thùng chứa, và sau đó tham gia chúng khi bạn muốn lấy lại dữ liệu. –
Trong tương lai, vui lòng đặt mã của bạn trực tiếp trong câu hỏi của bạn thay vì liên kết đến một trang web bên ngoài. – ildjarn
@Nicol. Bạn có chắc không? Theo tôi hiểu khi sử dụng std :: launch :: async nó sẽ hoạt động như thể một luồng được sinh ra. Theo http://en.cppreference.com/w/cpp/thread/async "Nếu chính sách & std :: launch :: async! = 0 (bit async được thiết lập), sinh ra một luồng mới thực hiện như thể bởi std :: thread (f, args ...), ngoại trừ nếu hàm f trả về một giá trị hoặc ném một ngoại lệ, nó được lưu trữ trong trạng thái chia sẻ có thể truy cập thông qua std :: future mà async trả về cho người gọi. " – petke