没有SendMessage的C++中的跨线程操作

Cross-thread operations in C++ without SendMessage

我正在寻找一种以 SendMessage 允许的方式执行跨线程操作的方法。换句话说,如何让一个线程在另一个线程中执行一些功能。但是我想在没有 SendMessage 的情况下这样做,因为这需要 window 并不总是可用。

同步异步都可以。

.NET 用 System.Windows.Threading.Dispatcher class 做到了,所以肯定有办法吗?

所以我猜我们在这里谈论 Windows OS,对吧?你应该在你的问题中指定。例如,Windows 的解决方案可能与 Linux 的解决方案不同。

现在,关于您的问题,针对该情况的任何解决方案都会迫使您的线程等待某个事件发生(将任务排入队列),或者无休止地轮询任务。

所以我们讨论的是某种互斥体、条件变量或某种特殊的休眠函数。

一种(简单)且不可移植的方式或将 "tasks" 发送到其他线程是使用内置的 Win32 - APC 机制(A同步P程序Call).

它利用了函数 QueueUserAPC and 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::queuestd::function<void()> 构建自己的任务队列。可以使用 std::condition_variable 代替睡眠状态。这是任何线程池为了获取和执行任务而在幕后所做的事情。如果您确实想要跨平台解决方案,我建议使用谷歌搜索 "C++ thread pool" 以查看此类任务队列的示例。