如何在 UWP C++/CX 中的对象的成员函数内使用 std::thread
How to use std::thread inside a member function of an object in UWP C++/CX
如何使用 std::thread
为 UWP 应用程序创建线程?抱歉,我对在对象内创建成员函数线程所需的语法有疑问。我刚开始在 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
它,这很糟糕,因为现在你可以拥有失控的线程;如果您关闭应用程序 window,您可能仍然有线程 运行,正在对正在销毁的数据进行操作。
更好的解决方案是将工作线程移动到 class 级别,在单击按钮时启动它(如果它尚未启动)并在 window 关闭时加入它。
但是:无论如何,所有这些都是无用的,因为在几乎每个 GUI 工具包(包括 UWP)中,G UI 对象 不是线程安全的 。从非主 UI 线程的线程调用它们的方法会导致不稳定的行为和崩溃,而您的代码正是这样做的。
有一些方法可以进行安全的跨线程 GUI 调用(通常归结为通过 GUI 事件队列传递消息)- this article 可能有一些 UWP - 相关建议 - 但这就像用大炮打蚊子;在您的情况下,您所需要的只是一个常规计时器,没有任何线程。
如何使用 std::thread
为 UWP 应用程序创建线程?抱歉,我对在对象内创建成员函数线程所需的语法有疑问。我刚开始在 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
它,这很糟糕,因为现在你可以拥有失控的线程;如果您关闭应用程序 window,您可能仍然有线程 运行,正在对正在销毁的数据进行操作。
更好的解决方案是将工作线程移动到 class 级别,在单击按钮时启动它(如果它尚未启动)并在 window 关闭时加入它。
但是:无论如何,所有这些都是无用的,因为在几乎每个 GUI 工具包(包括 UWP)中,G UI 对象 不是线程安全的 。从非主 UI 线程的线程调用它们的方法会导致不稳定的行为和崩溃,而您的代码正是这样做的。
有一些方法可以进行安全的跨线程 GUI 调用(通常归结为通过 GUI 事件队列传递消息)- this article 可能有一些 UWP - 相关建议 - 但这就像用大炮打蚊子;在您的情况下,您所需要的只是一个常规计时器,没有任何线程。