【问题标题】:How to use std::thread inside a member function of an object in UWP C++/CX如何在 UWP C++/CX 中的对象的成员函数中使用 std::thread
【发布时间】:2018-01-24 05:43:27
【问题描述】:

如何为 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 &&...)'

【问题讨论】:

  • 您的线程对象在创建后立即超出范围。你应该加入它,即th.join();
  • @Azeem 尽管我添加了th.join(),但它仍然不能解决问题。感谢您的建议
  • 我很久以前就放弃了bind-style 语法,只使用一个 lambda:std::thread th([this]{this-&gt;increment(5);});
  • @MatteoItalia 正是我想要的。谢谢!
  • 我会把它移到答案中。

标签: c++ multithreading c++-cx


【解决方案1】:

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

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

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

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

话虽如此,您的代码在多个级别上在逻辑上都是错误的。

正如评论中所述,由于您的线程立即超出范围,您将得到一个异常,因为 std::thread 不希望在线程结束之前被销毁,或者您明确地将创建的线程与线程对象。所以:

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

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

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

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

【讨论】:

    猜你喜欢
    • 2013-07-26
    • 2015-12-19
    • 1970-01-01
    • 1970-01-01
    • 2019-09-13
    • 1970-01-01
    • 1970-01-01
    • 2015-10-03
    • 2014-01-22
    相关资源
    最近更新 更多