- html - 出于某种原因,IE8 对我的 Sass 文件中继承的 html5 CSS 不友好?
- JMeter 在响应断言中使用 span 标签的问题
- html - 在 :hover and :active? 上具有不同效果的 CSS 动画
- html - 相对于居中的 html 内容固定的 CSS 重复背景?
我希望在保持事件循环运行的同时从 lambda 异步执行代码,我想:这可以工作...
auto thread = QSharedPointer<QThread>(new QThread);
QEventLoop l;
connect( thread.data(), &QThread::finished, &l, &QEventLoop::quit );
connect( thread.data(), &QThread::started, [=]() {
for(int i=0; i<100; ++i ) {
qDebug() << "waiting... " << i;
}
QThread::currentThread()->sleep(10);
} );
thread->start();
l.exec();
auto const fin = thread->wait();
qWarning() << fin;
一切都按预期工作,但是:当线程完成其 lambda 函数时,我没有得到该部分。似乎 finished
没有发出并且 wait
(即使没有额外的事件循环)将永远阻塞。
如何让事件循环退出或等待返回?或者有更好的方法让 lambda 在另一个线程中运行并使用非阻塞事件循环等待它?
谢谢
最佳答案
有两个问题:
从 QThread::started
到 lambda 的 connect
缺少给定线程的对象上下文。因此,lambda 将在当前线程中执行(特别是在 thread->thread()
中,这与 thread
不同!)。
您永远不会退出
线程。
对象上下文与线程不同。您需要一个存在于给定线程中的 QObject
;它不可能是线程本身。 QThread
实际上是一个线程句柄,并不意味着存在于它自己的线程中(它确实不是!)。抵制将 QThread
实例移动到它的线程的冲动:然后你会遇到一个句柄存在于它管理的线程中的悲惨情况。线程一结束,句柄就会变得无效,因为它会移动到空线程。
旁注:
QThread::sleep
是静态的。QEventLoop::quit
是线程安全的,即使它没有记录在案。您可以退出 lambda,从而节省一个连接。QThread thread;
QEventLoop loop;
QObject context;
context.moveToThread(&thread);
connect(&thread, &QThread::started, &context, [&]() {
qDebug() << "waiting... ";
QThread::sleep(10);
qDebug() << "done";
loop.quit();
});
thread.start();
loop.exec();
thread.quit();
thread.wait();
// some other code
唉,这导致重新进入事件循环和意大利面条代码:世界是异步的。无法保证您运行所有这些的方法不会从事件循环中重新进入。相反,您应该将控制权返回给基本事件循环。您还应该利用线程池,以免手动管理您的线程。线程的创建是昂贵的, transient 线程是一种反模式和过早的悲观情绪。当然,也许您的共享线程本应被重用,但即便如此您也很可能未充分利用它。全局线程池实例可以全局洞察整个应用程序的需求,并且可以更好地管理线程生命周期。
void doFirst() {
QtConcurrent::run([this]{
qDebug() << "waiting...";
QThread::sleep(10);
qDebug() << "done";
QObject src;
src.connect(&src, &QObject::destroyed, this, [this]{ doNext(); });
// see https://stackoverflow.com/q/21646467/1329652 for better ways
// of invoking doNext
});
}
void doNext() {
// some other code
}
有关在给定线程/对象上下文中执行代码的更好方法,请参阅 this question .
如果您的 lambda 是 I/O 绑定(bind)的,您应该为它们(并且只为它们)使用一个自定义的、更大的线程池。自 Qt 5.4 以来,QtConcurrent::run
可以将您的线程池作为第一个参数。
关于QThread 和 C++11 lambda : wait for finished,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/38769756/
这两者有区别吗? startActivity(intent); finish(); startActivity(intent); ThisActivityName.this.finish(); 注意:
我有一个包含大量 url 链接的 arrayOfLinks。我需要从这些链接中获取图像。我正在使用以下代码来执行此操作。 - (void)getImages { NSArray *links
我想创建一条执行以下步骤的路线 读取文件 将文件分割成行 使用 BeanIO 解码行 调用(昂贵且耗时的)处理器 我想在处理完所有线路后完成这条路线。 所以我的路线的基本布局如下所示: from("d
我正在使用 Nodejs。我有一个异步的 forEach,因为我必须在 forEach 中等待结果。结果,我需要等待 forEach 完成,然后继续处理循环的结果。我找到了几种等待 forEach 的
我正在编写需要背靠背内核调用的 android renderscript 代码(有时一个内核的输出成为另一个内核的输入)。我还有一些全局指针,绑定(bind)到 Java 层的内存。每个内核更新那些全
伪代码: void draw() { Vertex* vertices = scene.GetVertexArray(); glEnableClientState(...);
当我创建一个 Android 应用程序时,我首先在其中创建了主 Activity ,然后添加了启动 Activity 以及一个正常 Activity 。 所以我的问题是每当我在应用程序中单击退出时,它
我正在尝试将一些 API 数据获取到我的应用程序,并且我有两个 Activity 。第一个是启动屏幕(就像加载应用程序时谷歌使用的那样),我想知道在哪里调用 finish() 来结束 Activity
我使用 创建了“新文件” Activity startActivityForResult(new Intent(MainActivity.this, NewFile.class),1); NewFil
我有一个以 SingleTask 模式 (Android 2.2) 运行的 Activity ,该 Activity 从其他 Activity 或服务接收 Intent 。我的 Activity 将每
我编写了以下代码来使用 TextView 和按钮显示消息框。单击按钮时, Activity 应该完成。但这有时会起作用,但并不一致。有时它会挂起。如何让它始终如一地工作?请帮忙 public clas
我正在搜索,当 onDestroy 在 android 应用程序上执行时,我发现它是在设备资源不足(RAM、CPU) 时执行的,并且当用户调用 finish() 时。 例如,当我按下后退按钮从一个 A
我正在编写一个 Android 应用程序,它显示一个带有一些元素和一些 CRUD 操作的 RecyclerView。我想做的一件事是从我的 RecyclerView 更新现有元素,为此我打开一个新 A
被测试的 Activity 是一个简单的棋盘游戏。当满足游戏结束的必要条件时,在执行几项操作以显示谁赢了等之后,将运行以下代码: // Return to main menu after 5 seco
我有一个 Activity ,它创建了我创建的名为classA的类的新实例。在classA中,我有一个方法将对象添加到位于classA中的STATICarrayList。 所以我的 Activity
我正在使用 Facebook Android SDK,并希望在用户登录并获取用户对象后关闭我的 Activity。实际上,我存储了它的一部分,但无论如何我都想关闭该 Activity 。
我以前从事c# dotnet开发,有一个Application.exit()类型的方法,可以立即关闭应用程序并释放内存。 我发现 android 的“finish()”方法应该这样做 但它没有这样做,
我有一个 Activity ,我调用了 finish() 方法,但 Activity 没有从内存中清除。 调用 finish() 后,我看到方法 onDestroy() 已成功执行(并且我清除了其中的
我想在我的MKMapView上设置一个区域,然后找到与 map 的东北角和西南角对应的坐标。 This code works just fine to do that: //Recenter and
我正在尝试使用从顶部滑动动画将一个 View 替换为另一个 View 。我有点遵循 http://gentlebytes.com/2011/09/auto-layout-in-lion/ 中发布的指南
我是一名优秀的程序员,十分优秀!