我正在寻找一种以SendMessage允许的方式执行跨线程操作的方法。换句话说,如何让一个线程在另一个线程中执行某个函数。但我想在没有SendMessage的情况下这样做,因为这需要一个并不总是可用的窗口。
同步或异步都没问题。
.NET使用System.Windows.Threading.Dispatcher类完成它,所以肯定有办法吗?
答案 0 :(得分:0)
所以我猜我们在这里谈论的是Windows操作系统,对吗?你应该在你的问题中指明。例如,Windows的解决方案可能与Linux的解决方案不同。
现在,关于你的问题,针对这种情况的任何解决方案都会迫使你的线程等待某个事件发生(排队任务),或者无休止地轮询任务。
所以我们谈论的是某种互斥体,条件变量或某种特殊的睡眠功能。
一种(简单)和非便携方式或向其他线程发送“任务”是使用内置Win32 - APC
的机制( A 同步 P rocedure C 全部。)
它使用函数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
。这就是任何线程池在幕后为了获取和执行任务而做的事情。如果您确实需要跨平台解决方案,我建议使用Google搜索“C ++线程池”以查看此类任务队列的示例。