如何在 UWP C++/CX 中对象的成员函数中使用 std::thread

How to use std::thread inside a member function of an object in UWP C++/CX

本文关键字:函数 成员 thread std 对象 UWP C++ CX      更新时间:2023-10-16

如何使用 UWP 应用程序的std::thread创建线程?抱歉,我在对象内创建成员函数线程所需的语法有问题。我刚开始在Visual Studio中使用c ++/cx。这是我的代码:

void MainPage::increment(int val)
{
for (int i = 0; i < val; ++i){
m_timer4++;
Sleep(100);
textBox4->Text = m_timer4.ToString();
}
}
void _4ThreadsUWP::MainPage::button_Click(Platform::Object^ sender, Windows::UI::Xaml::RoutedEventArgs^ e)
{
m_timer->Start();
std::thread th(&MainPage::increment, this, 5);
}

编辑:

我遇到这些错误:

错误 1:

'std::invoke': no matching overloaded function found

错误 2:

Failed to specialize function template 'unknown-type std::invoke(_Callable &&,_Types &&...)'

我不知道你的构造函数调用到底出了什么问题 - 绑定样式的语法是出了名的古怪,并且给出了最糟糕的错误消息。

我的建议是完全避免std::bind及其不圣洁的兄弟(例如这个std::thread构造函数(,并尽可能使用 lambda 函数。它们有自己的怪癖,但它们通常更容易理解,错误消息不是完全的垃圾,它们有更多的应用程序。

在这种情况下,您可以只做:

std::thread th([this]{this->increment(5);});

话虽如此,您的代码在多个层面上在逻辑上是错误的。

正如在注释中已经指出的那样,由于您的线程立即超出范围,因此您将获得异常,因为std::thread不希望在线程结束或您显式将创建的线程与线程对象分离之前被销毁。所以:

  • 要么你调用join,在这种情况下是没有意义的,因为现在你的主线程将停止等待工作线程,所以启动线程首先是无用的;
  • 或者你detach它,这很糟糕,因为现在你可以有失控的线程;如果你关闭应用程序窗口,你可能仍然有线程在运行,对正在销毁的数据进行操作。

更好的解决方案是在类级别移动工作线程,单击按钮时启动它(如果尚未启动(,并在窗口关闭时加入它。

但是:无论如何,所有这些都是无用的,因为在几乎每个 GUI 工具包(包括 UWP(中,GUI 对象都不是线程安全的。从不是主 UI 线程的线程调用其方法会导致行为不稳定并崩溃,而您的代码正是这样做的。

有一些方法可以进行安全的跨线程 GUI 调用(通常归结为通过 GUI 事件队列传递消息( - 本文可能有一些与 UWP 相关的建议 - 但这就像用大炮射击蚊子;在您的情况下,您只需要一个常规计时器,没有任何线程。