我正在尋找一種以SendMessage允許的方式執行跨線程操作的方法。換句話說,如何讓一個線程在另一個線程中執行某個函數。但是我想在沒有SendMessage的情況下這樣做,因爲這需要一個並不總是可用的窗口。C++中無SendMessage的跨線程操作
同步或異步很好。
.NET與System.Windows.Threading.Dispatcher類一起使用,所以肯定有辦法嗎?
我正在尋找一種以SendMessage允許的方式執行跨線程操作的方法。換句話說,如何讓一個線程在另一個線程中執行某個函數。但是我想在沒有SendMessage的情況下這樣做,因爲這需要一個並不總是可用的窗口。C++中無SendMessage的跨線程操作
同步或異步很好。
.NET與System.Windows.Threading.Dispatcher類一起使用,所以肯定有辦法嗎?
所以我猜我們在這裏談論Windows操作系統,對吧?你應該在你的問題中指定。例如,針對Windows的解決方案可能與Linux的解決方案不同。
現在,對於您的問題,任何針對該情況的解決方案都會強制您的線程等待某個事件發生(排隊任務),或者無休止地輪詢任務。
所以我們正在討論某種互斥體,條件變量或某種特殊的睡眠函數。
一(簡單)和非便攜式的方式或發送「任務」給其他線程是使用內置的Win32 - 的APC
機構(甲同步P rocedure Ç全部)。
它採用了功能QueueUserAPC和SleepEx,我有小在我的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::queue
和std::function<void()>
構建自己的任務隊列。而不是睡在警戒狀態,可以用std::condition_variable
代替。這是任何線程池在幕後執行以獲取和執行任務。如果您確實需要跨平臺解決方案,我建議您使用「C++線程池」來查看此類任務隊列的示例。
謝謝,QueueUserAPC正是我所需要的。你知道是否有一個同步等效? – user1610015
在本文中定義爲同步。 –
它聽起來像真的......就像APC中「A」的相反。也許像QueueUserSPC? :D – user1610015
您需要一個工作隊列,目標線程被卡住處理其項目,這正是Dispatcher類在.NET中提供的。 –
我需要使用哪些功能?我正在看「線程池API」文檔,但它似乎只能對特殊的工作線程排隊操作。如果工作線程需要在主UI線程上對操作進行排隊呢? – user1610015
對於不習慣於本地Windows開發的人來說,這看起來很奇怪,但有一個隱形窗口非常普遍。在很多情況下,即使線程從不顯示單個用戶可見元素,線程也需要一個線程,這是完全可以接受的。因此,如果您必須交換或收聽消息,請創建一個窗口。雖然解釋你的實際問題可能是一個好主意 - 但你很少必須在特定的線程上執行某些操作。 – Voo