2016-12-25 83 views
0

我正在尋找一種以SendMessage允許的方式執行跨線程操作的方法。換句話說,如何讓一個線程在另一個線程中執行某個函數。但是我想在沒有SendMessage的情況下這樣做,因爲這需要一個並不總是可用的窗口。C++中無SendMessage的跨線程操作

同步或異步很好。

.NET與System.Windows.Threading.Dispatcher類一起使用,所以肯定有辦法嗎?

+1

您需要一個工作隊列,目標線程被卡住處理其項目,這正是Dispatcher類在.NET中提供的。 –

+0

我需要使用哪些功能?我正在看「線程池API」文檔,但它似乎只能對特殊的工作線程排隊操作。如果工作線程需要在主UI線程上對操作進行排隊呢? – user1610015

+1

對於不習慣於本地Windows開發的人來說,這看起來很奇怪,但有一個隱形窗口非常普遍。在很多情況下,即使線程從不顯示單個用戶可見元素,線程也需要一個線程,這是完全可以接受的。因此,如果您必須交換或收聽消息,請創建一個窗口。雖然解釋你的實際問題可能是一個好主意 - 但你很少必須在特定的線程上執行某些操作。 – Voo

回答

0

所以我猜我們在這裏談論Windows操作系統,對吧?你應該在你的問題中指定。例如,針對Windows的解決方案可能與Linux的解決方案不同。

現在,對於您的問題,任何針對該情況的解決方案都會強制您的線程等待某個事件發生(排隊任務),或者無休止地輪詢任務。

所以我們正在討論某種互斥體,條件變量或某種特殊的睡眠函數。

一(簡單)和非便攜式的方式或發送「任務」給其他線程是使用內置的Win32 - 的APC機構(同步P rocedure Ç全部)。

它採用了功能QueueUserAPCSleepEx,我有小在我的Windows 10 + Visual Studio的測試,該解決方案2015年

namespace details { 
    void waitforTask() noexcept { 
     SleepEx(INFINITE, TRUE); 
    } 

    void __stdcall executeTask(ULONG_PTR ptr) { 
     if (ptr == 0) { 
      return; 
     } 
     std::unique_ptr<std::function<void()>> scopedPtr(reinterpret_cast<std::function<void()>*>(ptr)); 
     (*scopedPtr)(); 
    } 
} 

template<class F, class ... Args> 
void sendTask(void* threadHandle, F&& f, Args&& ... args) { 
    auto task = 
     std::make_unique<std::function<void()>>(std::bind(std::forward<F>(f), std::forward<Args>(args)...)); 

    const auto res = QueueUserAPC(&details::executeTask, 
     threadHandle, 
     reinterpret_cast<ULONG_PTR>(task.get())); 
    if (res == 0) { 
     throw std::runtime_error("sendTask failed."); 
    } 

    task.release(); 
} 

使用例:

std::thread thread([] { 
     for (;;) { 
      details::waitforTask(); 
     } 
    }); 

    sendTask(thread.native_handle(), [](auto literal) { 
     std::cout << literal; 
    }, "hello world"); 

該解決方案還展示瞭如何使用Win32沒有實際污染用C++代碼非相關的win32代碼編寫的業務邏輯。

此解決方案也可以適應跨平臺解決方案,而不是使用內部的,半文檔化的win32任務隊列,可以使用std::queuestd::function<void()>構建自己的任務隊列。而不是睡在警戒狀態,可以用std::condition_variable代替。這是任何線程池在幕後執行以獲取和執行任務。如果您確實需要跨平臺解決方案,我建議您使用「C++線程池」來查看此類任務隊列的示例。

+0

謝謝,QueueUserAPC正是我所需要的。你知道是否有一個同步等效? – user1610015

+0

在本文中定義爲同步。 –

+0

它聽起來像真的......就像APC中「A」的相反。也許像QueueUserSPC? :D – user1610015