簡體   English   中英

在std :: packaged_task中使用成員函數

[英]Use member function in std::packaged_task

我想做的應該很容易,但我不明白......

我想要做的就是在某個特定時間點在后台啟動類的成員函數。 該功能的結果也應該是“外部”可用的。 所以我想在構造函數中准備任務(設置future變量,...)並在稍后的某個時間啟動它。

我試圖結合std ::(packaged_task | async | future),但我沒有讓它工作。

這段代碼不會編譯,但我認為它顯示了我想要做的事情:

class foo {
private:
  // This function shall run in background as a thread
  // when it gets triggered to start at some certain point
  bool do_something() { return true; }

  std::packaged_task<bool()> task;
  std::future<bool> result;

public:
  foo() : 
    task(do_something), // yes, that's wrong, but how to do it right?
    result(task.get_future()) 
  {
    // do some initialization stuff
    .....
  }
  ~foo() {}

  void start() {
    // Start Task as asynchron thread
    std::async as(std::launch::async, task); // Also doesn't work...
  }

  // This function should return the result of do_something
  bool get_result() { return result.get(); }
};

提前致謝!

只需使用std::bind()

#include <functional> // For std::bind()

foo() :
    task(std::bind(&foo::do_something, this)),
//       ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
    result(task.get_future()) 
{
    //  ...
}

而且,你在這里做錯了:

std::async as(std::launch::async, task)
//         ^^
//         Trying to declare a variable?

因為你想要的是調用std::async()函數,而不是聲明一個(不存在的)類型的對象std::async() 因此,作為第一步,將其更改為:

std::async(std::launch::async, task)

但請注意,這不足以使任務異步運行:由於std::async()的奇怪行為,當返回的未來被丟棄時,您的任務將始終執行,就像您同步啟動它一樣 -返回的future對象的析構函數將阻塞,直到完成操作。 (*)

要解決最后一個問題,可以在result成員變量中保存返回的future(而不是在構造時將std::packaged_task::get_future()返回的result分配給result ):

    result = std::async(std::launch::async, task);
//  ^^^^^^^^

(*)我認為 MSVC忽略了這個規范,實際上是異步執行任務。 因此,如果您正在使用VS2012,您可能不會遇到此問題。

編輯:

正如Praetorian在他的回答中正確提到的 ,上述內容仍然存在問題,因為在async()的實現中會嘗試使用packaged_task的副本。 要解決此問題,請使用std::ref()task對象包裝在引用包裝器中。

do_something()是一個成員函數,這意味着它將一個隱式this指針作為第一個參數。 你需要bind this指針,或者創建一個調用do_something的lamda。

foo() : 
  task(std::bind(&foo::do_something, this)),
  result(task.get_future()) 
{}

要么

foo() : 
  task([this]{ return do_something(); }),
  result(task.get_future()) 
{}

std::async as(std::launch::async, task);

std::async是一個函數模板,而不是一個類型。 所以明顯的變化是

std::async(std::launch::async, task);

但是這會導致另一個錯誤,因為在該調用的內部某處嘗試了一個task副本,但是std::packaged_task有一個已刪除的拷貝構造函數。 你可以通過使用std::ref來解決這個問題,這將避免復制。

std::async(std::launch::async, std::ref(task));

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM