簡體   English   中英

在不同的線程中調用std :: function

[英]Call std::function in different thread

我正在一個c ++框架中工作,主要是在c ++ 11之前編寫的,它使我們能夠將事件從線程觸發到另一個線程(假設接收線程正在運行事件隊列,因此它主要用於觸發事件以主UI線程(來自幫助程序線程)。

當前,實現此目的的代碼非常冗長-需要我們定義兩個類:

  1. 一個事件類,其中包含我們要傳輸的任何信息。
  2. 在接收線程中處理事件的偵聽器類。

我們最近已移至c ++ 11/14,並一直在努力更新許多代碼以使用智能指針,標准容器和lambda。 我想編寫一個通用類,使我可以發送lambda以便在其他線程中運行。 就像是:

mBoundary = make_unique<ThreadBoundary>( []( int value ) { doSomething( value ); } ); 
mBoundary->callInMainThread( 47 );

ThreadBoundary boundary2( []( std::string value ) { displayString( value ); } );
boundary2.callInMainThreadWait( "Show this string to the user" );

作為最初的嘗試,我目前正在使用不帶任何參數的lambda進行工作,該lambda基於當前框架功能(省略錯誤檢查,清除等)構建:

class ThreadBoundary
{
public:
    ThreadBoundary( std::function<void()> function ):mFunction( function )
    {
        mListener = make_shared<ThreadBoundaryListener>();
        cApplication::addThreadBoundaryListener( mListener );
    }

    void callInMainThread()
    {
        cApplication::fireEventInMainThread( new ThreadBoundaryEvent( mFunction ) );
    }

    class ThreadBoundaryEvent:public FrameworkThreadBoundaryEvent
    {
    public:
        ThreadBoundaryEvent( std::function<void()> function )
        {
            mFunction = function;
        }

        void call() { mFunction(); }

    private:
        std::function<void()> mFunction;
    };

    class ThreadBoundaryListener:public FrameworkThreadBoundaryListener
    {
    public:
        ThreadBoundaryListener() {}

        void handleEvent( const FrameworkThreadBoundaryEvent* event )
        {
            dynamic_cast<const ThreadBoundaryEvent*>( event )->call();
        }
    };

private:
    shared_ptr<ThreadBoundaryListener> mListener;
    std::function<void()> mFunction;
};

這使我可以將“一次性”事件觸發到主線程,但是,由於無法發送參數,因此它的功能非常有限。

我想讓此類使用可變參數模板,以便可以將任何內容傳遞給callInMainThread函數。 但是,我還無法弄清楚如何在事件中存儲參數包並將其傳遞給call()內部的函數。 所以我的問題是:

  1. 是否可以存儲參數包,然后將其傳遞給std :: function?
  2. 在c ++ 11/14中是否有更好的方法可以完成此操作,而無需進行大量重新設計? 我們的框架目前正在包裝OS功能以實現此目的(即,在Windows上,它使用OS X中的SendMessage與performSelectorOnMainThread)。

不要將接口構造與調用分開,而應使用lambda的功能將參數捕獲到函數對象本身(閉包)中,以便每次調用都相同。 沒有基本的線程通信對象封裝函數類型。 而是在調用時傳遞整個函數。 轉到此界面:

threadBoundary.callInMainThread([value](){doSomething(value);});

如果您傳遞的所有內容都是不帶參數的函數對象,那么傳遞和調用都很容易。 捕獲您需要通過的所有內容。

有關一些接口和實現的想法,請查看boost::asio如何實現其io_service ,它使您可以像這樣將函數調用發布到其他線程。

空函數調用更容易跨線程邊界發送。 而且很容易捕獲要傳遞到lambda捕獲列表中的參數。

我會接受的。

但是,您可以編寫代碼將非空函數調用轉換為空函數。 如果要“凍結”不帶參數的函數調用,則簽名也必須凍結。

tempate<class Sig>
struct freeze_function;
tempate<class R, class...Args>
struct freeze_function<R(Args...)> {
  std::function< R(Args...) > to_freeze;
  freeze_function() = default;
  freeze_function( freeze_function&& ) = default;
  freeze_function( freeze_function const& ) = default;
  freeze_function& operator=( freeze_function&& ) = default;
  freeze_function& operator=( freeze_function const& ) = default;
  freeze_function( std::function< void(Args...) > f ):to_freeze(std::move(f)) {}

  std::function<R()> operator()( Args... args ) const {
    return [=, frozen=this->to_freeze]->R{
      return frozen( args... );
    };
  }
};

可以通過采用int的lambda構造freeze_function<void(int)> 然后,您可以將其傳遞給一個int並且它返回帶有該int綁定的std::function<void()>

但是我認為這不是必需的。

(為了從freeze_function獲得最佳效率需要進行額外的工作;它不必要地復制args...freeze_function args...扔到一個元組中,然后在lambda中解壓縮它們,也許使用等效於std::apply from C ++ 17)。

可以通過添加簽名(使其成為模板)將其烘焙到ThreadBoundary ,也可以將未實現的函數調用存儲在某個位置,並在將生成的std::function<void()>傳遞給ThreadBoundary之前立即凍結它們。 。

錯誤:沒有匹配的 function 調用 'std::thread::_Invoker <std::tuple< div><div id="text_translate"><p> 我正面臨線程問題。</p><p> 我試圖在 Chronometer class 的線程內執行 function,包括一個 while 循環:</p><p> 這是部分代碼:</p><pre> for(int i = 0; i<car_data.size();i++) { if(car_data[i]->checkArea(frame, pt1_zone, pt2_zone)) { std::thread(&Chronometer::start_chrono, car_crono[i], std::ref(chrono)); cv::rectangle(frame, car_data[i]->pt1, car_data[i]->pt2, cv::Scalar(255,0,0), 1, cv::LINE_8,0); //cv::putText(frame, "Parked", car_data[i]->pt1, cv::FONT_HERSHEY_DUPLEX, 0.9, cv::Scalar( 50, 255, 50 )); //occupancy_state = place.occupancyTrue(); //place_1.occupancy = true;</pre><p> car_crono 和 chrono 的類型</p><pre>std::vector<Chronometer*> car_crono; Chronometer chrono;</pre><p> 這是我的 class 計時器:</p><pre> class Chronometer { private: static int hour, min, sec; //std::stringstream ss; //Chronometer chrono; public: Chronometer(); static Chronometer& start_chrono(Chronometer& chrono); static Chronometer& finish_chrono(Chronometer& chrono); friend std::ostream& operator<<(std::ostream& flux, Chronometer t); Chronometer& operator=(const Chronometer& other); ~Chronometer(); };</pre><p> 對於線程,我嘗試了幾種參數。 最后一個:</p><pre> std::thread(&Chronometer::start_chrono, car_crono[i], std::ref(chrono));</pre><p> 我猜 ref 是必要的,但沒有改變。</p><p> 這是完整的錯誤</p><pre>/usr/include/c++/7/thread: In instantiation of 'struct std::thread::_Invoker<std::tuple<Chronometer& (*)(Chronometer&), Chronometer*, std::reference_wrapper<Chronometer> > >': /usr/include/c++/7/thread:127:22: required from 'std::thread::thread(_Callable&&, _Args&&...) [with _Callable = Chronometer& (*)(Chronometer&); _Args = {Chronometer*&, std::reference_wrapper<Chronometer>}]' recognizer_rtsp.cxx:348:76: required from here /usr/include/c++/7/thread:240:2: error: no matching function for call to 'std::thread::_Invoker<std::tuple<Chronometer& (*)(Chronometer&), Chronometer*, std::reference_wrapper<Chronometer> > >::_M_invoke(std::thread::_Invoker<std::tuple<Chronometer& (*)(Chronometer&), Chronometer*, std::reference_wrapper<Chronometer> > >::_Indices)' operator()() ^~~~~~~~ /usr/include/c++/7/thread:231:4: note: candidate: template<long unsigned int..._Ind> decltype (std::__invoke((_S_declval<_Ind>)()...)) std::thread::_Invoker<_Tuple>::_M_invoke(std::_Index_tuple<_Ind...>) [with long unsigned int..._Ind = {_Ind...}; _Tuple = std::tuple<Chronometer& (*)(Chronometer&), Chronometer*, std::reference_wrapper<Chronometer> >] _M_invoke(_Index_tuple<_Ind...>) ^~~~~~~~~ /usr/include/c++/7/thread:231:4: note: template argument deduction/substitution failed: /usr/include/c++/7/thread: In substitution of 'template<long unsigned int..._Ind> decltype (std::__invoke(_S_declval<_Ind>()...)) std::thread::_Invoker<std::tuple<Chronometer& (*)(Chronometer&), Chronometer*, std::reference_wrapper<Chronometer> > >::_M_invoke<_Ind...>(std::_Index_tuple<_Ind1...>) [with long unsigned int..._Ind = {0, 1, 2}]': /usr/include/c++/7/thread:240:2: required from 'struct std::thread::_Invoker<std::tuple<Chronometer& (*)(Chronometer&), Chronometer*, std::reference_wrapper<Chronometer> > >' /usr/include/c++/7/thread:127:22: required from 'std::thread::thread(_Callable&&, _Args&&...) [with _Callable = Chronometer& (*)(Chronometer&); _Args = {Chronometer*&, std::reference_wrapper<Chronometer>}]' recognizer_rtsp.cxx:348:76: required from here /usr/include/c++/7/thread:233:29: error: no matching function for call to '__invoke(std::__tuple_element_t<0, std::tuple<Chronometer& (*)(Chronometer&), Chronometer*, std::reference_wrapper<Chronometer> > >, std::__tuple_element_t<1, std::tuple<Chronometer& (*)(Chronometer&), Chronometer*, std::reference_wrapper<Chronometer> > >, std::__tuple_element_t<2, std::tuple<Chronometer& (*)(Chronometer&), Chronometer*, std::reference_wrapper<Chronometer> > >)' -> decltype(std::__invoke(_S_declval<_Ind>()...)) ~~~~~~~~~~~~~^~~~~~~~~~~~~~~~~~~~~~~ In file included from /usr/include/c++/7/tuple:41:0, from /usr/include/c++/7/bits/stl_map.h:63, from /usr/include/c++/7/map:61, from../alpr_utils.h:7, from recognizer_rtsp.cxx:34: /usr/include/c++/7/bits/invoke.h:89:5: note: candidate: template<class _Callable, class... _Args> constexpr typename std::__invoke_result<_Functor, _ArgTypes>::type std::__invoke(_Callable&&, _Args&&...) __invoke(_Callable&& __fn, _Args&&... __args) ^~~~~~~~ /usr/include/c++/7/bits/invoke.h:89:5: note: template argument deduction/substitution failed: /usr/include/c++/7/bits/invoke.h: In substitution of 'template<class _Callable, class... _Args> constexpr typename std::__invoke_result<_Functor, _ArgTypes>::type std::__invoke(_Callable&&, _Args&&...) [with _Callable = Chronometer& (*)(Chronometer&); _Args = {Chronometer*, std::reference_wrapper<Chronometer>}]': /usr/include/c++/7/thread:233:29: required by substitution of 'template<long unsigned int..._Ind> decltype (std::__invoke(_S_declval<_Ind>()...)) std::thread::_Invoker<std::tuple<Chronometer& (*)(Chronometer&), Chronometer*, std::reference_wrapper<Chronometer> > >::_M_invoke<_Ind...>(std::_Index_tuple<_Ind1...>) [with long unsigned int..._Ind = {0, 1, 2}]' /usr/include/c++/7/thread:240:2: required from 'struct std::thread::_Invoker<std::tuple<Chronometer& (*)(Chronometer&), Chronometer*, std::reference_wrapper<Chronometer> > >' /usr/include/c++/7/thread:127:22: required from 'std::thread::thread(_Callable&&, _Args&&...) [with _Callable = Chronometer& (*)(Chronometer&); _Args = {Chronometer*&, std::reference_wrapper<Chronometer>}]' recognizer_rtsp.cxx:348:76: required from here /usr/include/c++/7/bits/invoke.h:89:5: error: no type named 'type' in 'struct std::__invoke_result<Chronometer& (*)(Chronometer&), Chronometer*, std::reference_wrapper<Chronometer> >'</pre><p> 我應該通過線程傳遞什么樣的參數?</p><p> 我去了幾個鏈接來尋找解決方案,但沒有什么能解決我的問題:</p><p> <a href="https://stackoverflow.com/questions/21048906/stdthread-pass-by-reference-calls-copy-constructor" rel="nofollow noreferrer">std::thread 通過引用傳遞調用復制構造函數</a></p><p> <a href="https://stackoverflow.com/questions/67625058/no-matching-function-to-invoke-using-stdthread" rel="nofollow noreferrer">沒有匹配的 function 調用,使用 std::thread</a></p><p> ... </p></div></std::tuple<>

[英]error: no matching function for call to ‘std::thread::_Invoker<std::tuple

暫無
暫無

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

相關問題 包裝std :: thread調用函數 使用std :: async從線程進行函數調用? 錯誤:沒有用於調用 std::thread 的匹配函數 使用不同的參數函數運行std :: thread 錯誤:沒有匹配的 function 調用 'std::thread::_Invoker <std::tuple< div><div id="text_translate"><p> 我正面臨線程問題。</p><p> 我試圖在 Chronometer class 的線程內執行 function,包括一個 while 循環:</p><p> 這是部分代碼:</p><pre> for(int i = 0; i<car_data.size();i++) { if(car_data[i]->checkArea(frame, pt1_zone, pt2_zone)) { std::thread(&Chronometer::start_chrono, car_crono[i], std::ref(chrono)); cv::rectangle(frame, car_data[i]->pt1, car_data[i]->pt2, cv::Scalar(255,0,0), 1, cv::LINE_8,0); //cv::putText(frame, "Parked", car_data[i]->pt1, cv::FONT_HERSHEY_DUPLEX, 0.9, cv::Scalar( 50, 255, 50 )); //occupancy_state = place.occupancyTrue(); //place_1.occupancy = true;</pre><p> car_crono 和 chrono 的類型</p><pre>std::vector<Chronometer*> car_crono; Chronometer chrono;</pre><p> 這是我的 class 計時器:</p><pre> class Chronometer { private: static int hour, min, sec; //std::stringstream ss; //Chronometer chrono; public: Chronometer(); static Chronometer& start_chrono(Chronometer& chrono); static Chronometer& finish_chrono(Chronometer& chrono); friend std::ostream& operator<<(std::ostream& flux, Chronometer t); Chronometer& operator=(const Chronometer& other); ~Chronometer(); };</pre><p> 對於線程,我嘗試了幾種參數。 最后一個:</p><pre> std::thread(&Chronometer::start_chrono, car_crono[i], std::ref(chrono));</pre><p> 我猜 ref 是必要的,但沒有改變。</p><p> 這是完整的錯誤</p><pre>/usr/include/c++/7/thread: In instantiation of 'struct std::thread::_Invoker<std::tuple<Chronometer& (*)(Chronometer&), Chronometer*, std::reference_wrapper<Chronometer> > >': /usr/include/c++/7/thread:127:22: required from 'std::thread::thread(_Callable&&, _Args&&...) [with _Callable = Chronometer& (*)(Chronometer&); _Args = {Chronometer*&, std::reference_wrapper<Chronometer>}]' recognizer_rtsp.cxx:348:76: required from here /usr/include/c++/7/thread:240:2: error: no matching function for call to 'std::thread::_Invoker<std::tuple<Chronometer& (*)(Chronometer&), Chronometer*, std::reference_wrapper<Chronometer> > >::_M_invoke(std::thread::_Invoker<std::tuple<Chronometer& (*)(Chronometer&), Chronometer*, std::reference_wrapper<Chronometer> > >::_Indices)' operator()() ^~~~~~~~ /usr/include/c++/7/thread:231:4: note: candidate: template<long unsigned int..._Ind> decltype (std::__invoke((_S_declval<_Ind>)()...)) std::thread::_Invoker<_Tuple>::_M_invoke(std::_Index_tuple<_Ind...>) [with long unsigned int..._Ind = {_Ind...}; _Tuple = std::tuple<Chronometer& (*)(Chronometer&), Chronometer*, std::reference_wrapper<Chronometer> >] _M_invoke(_Index_tuple<_Ind...>) ^~~~~~~~~ /usr/include/c++/7/thread:231:4: note: template argument deduction/substitution failed: /usr/include/c++/7/thread: In substitution of 'template<long unsigned int..._Ind> decltype (std::__invoke(_S_declval<_Ind>()...)) std::thread::_Invoker<std::tuple<Chronometer& (*)(Chronometer&), Chronometer*, std::reference_wrapper<Chronometer> > >::_M_invoke<_Ind...>(std::_Index_tuple<_Ind1...>) [with long unsigned int..._Ind = {0, 1, 2}]': /usr/include/c++/7/thread:240:2: required from 'struct std::thread::_Invoker<std::tuple<Chronometer& (*)(Chronometer&), Chronometer*, std::reference_wrapper<Chronometer> > >' /usr/include/c++/7/thread:127:22: required from 'std::thread::thread(_Callable&&, _Args&&...) [with _Callable = Chronometer& (*)(Chronometer&); _Args = {Chronometer*&, std::reference_wrapper<Chronometer>}]' recognizer_rtsp.cxx:348:76: required from here /usr/include/c++/7/thread:233:29: error: no matching function for call to '__invoke(std::__tuple_element_t<0, std::tuple<Chronometer& (*)(Chronometer&), Chronometer*, std::reference_wrapper<Chronometer> > >, std::__tuple_element_t<1, std::tuple<Chronometer& (*)(Chronometer&), Chronometer*, std::reference_wrapper<Chronometer> > >, std::__tuple_element_t<2, std::tuple<Chronometer& (*)(Chronometer&), Chronometer*, std::reference_wrapper<Chronometer> > >)' -> decltype(std::__invoke(_S_declval<_Ind>()...)) ~~~~~~~~~~~~~^~~~~~~~~~~~~~~~~~~~~~~ In file included from /usr/include/c++/7/tuple:41:0, from /usr/include/c++/7/bits/stl_map.h:63, from /usr/include/c++/7/map:61, from../alpr_utils.h:7, from recognizer_rtsp.cxx:34: /usr/include/c++/7/bits/invoke.h:89:5: note: candidate: template<class _Callable, class... _Args> constexpr typename std::__invoke_result<_Functor, _ArgTypes>::type std::__invoke(_Callable&&, _Args&&...) __invoke(_Callable&& __fn, _Args&&... __args) ^~~~~~~~ /usr/include/c++/7/bits/invoke.h:89:5: note: template argument deduction/substitution failed: /usr/include/c++/7/bits/invoke.h: In substitution of 'template<class _Callable, class... _Args> constexpr typename std::__invoke_result<_Functor, _ArgTypes>::type std::__invoke(_Callable&&, _Args&&...) [with _Callable = Chronometer& (*)(Chronometer&); _Args = {Chronometer*, std::reference_wrapper<Chronometer>}]': /usr/include/c++/7/thread:233:29: required by substitution of 'template<long unsigned int..._Ind> decltype (std::__invoke(_S_declval<_Ind>()...)) std::thread::_Invoker<std::tuple<Chronometer& (*)(Chronometer&), Chronometer*, std::reference_wrapper<Chronometer> > >::_M_invoke<_Ind...>(std::_Index_tuple<_Ind1...>) [with long unsigned int..._Ind = {0, 1, 2}]' /usr/include/c++/7/thread:240:2: required from 'struct std::thread::_Invoker<std::tuple<Chronometer& (*)(Chronometer&), Chronometer*, std::reference_wrapper<Chronometer> > >' /usr/include/c++/7/thread:127:22: required from 'std::thread::thread(_Callable&&, _Args&&...) [with _Callable = Chronometer& (*)(Chronometer&); _Args = {Chronometer*&, std::reference_wrapper<Chronometer>}]' recognizer_rtsp.cxx:348:76: required from here /usr/include/c++/7/bits/invoke.h:89:5: error: no type named 'type' in 'struct std::__invoke_result<Chronometer& (*)(Chronometer&), Chronometer*, std::reference_wrapper<Chronometer> >'</pre><p> 我應該通過線程傳遞什么樣的參數?</p><p> 我去了幾個鏈接來尋找解決方案,但沒有什么能解決我的問題:</p><p> <a href="https://stackoverflow.com/questions/21048906/stdthread-pass-by-reference-calls-copy-constructor" rel="nofollow noreferrer">std::thread 通過引用傳遞調用復制構造函數</a></p><p> <a href="https://stackoverflow.com/questions/67625058/no-matching-function-to-invoke-using-stdthread" rel="nofollow noreferrer">沒有匹配的 function 調用,使用 std::thread</a></p><p> ... </p></div></std::tuple<> C ++ 11 std :: thread給出錯誤:沒有匹配函數來調用std :: thread :: thread std :: function vs auto調用不同的重載 std線程調用模板成員函數模板類:編譯錯誤 使用char指針函數和std :: string調用線程會產生不同的結果 用函數構造一個std :: thread
 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM