终止正在 Q​​Thread 内运行的正在进行的 QProcess? [复制]

2023-11-29

如何终止正在 Q​​Thread 内运行并被另一个 QThread 删除的正在进行的 QProcess?我什至插入了一个 QMutex extCmdProcessLock,这应该避免在 extCmdProcess 完成或超时之前破坏 DbManager。 如果另一个线程在 DbManager 上调用删除,我会在“waitForStarted”上遇到分段错误。 我无法使用信号(我认为),因为我在顺序数据进程中使用外部命令。 非常感谢您的帮助!

DbManager::extCmd(){
    ...
    QMutexLocker locker(&extCmdProcessLock);
    extCmdProcess = new QProcess(this);
    QString argStr  += " --p1=1"
                    +  " --p2=3";
    extCmdProcess->start(cmd,argStr.split(QString(" ")));
    bool startedSuccessfully = extCmdProcess->waitForStarted();
    if (!startedSuccessfully) {
       extCmdProcess->close();
       extCmdProcess->kill();
       extCmdProcess->waitForFinished();
       delete extCmdProcess;
       extCmdProcess = NULL;
       return;
    }
    bool successfullyFinished = extCmdProcess->waitForFinished(-1);
    if (!successfullyFinished) {
       qDebug() << "finishing failed"; // Appendix C
       extCmdProcess->close();
       extCmdProcess->kill();
       extCmdProcess->waitForFinished(-1);
       delete extCmdProcess;
       extCmdProcess = NULL;
       return;
   }
   extCmdProcess->close();
   delete extCmdProcess;
   extCmdProcess = NULL;
}

DbManager::~DbManager(){
    qDebug() << "DB DbManager destructor called.";   
    QMutexLocker locker(&extCmdProcessLock);
    if (extCmdProcess!= NULL){
       this->extCmdProcess->kill(); // added after Appendix A
       this->extCmdProcess->waitForFinished();
    }
}

附录A:我还收到错误“QProcess:进程仍在运行时已被销毁”。我读到这可能意味着在 waitForStarted() 命令尚未完成时执行了来自其他线程的“删除 dbmanager”调用。但我真的想知道为什么我的析构函数中的kill()命令没有解决这个问题。

附录 B:根据评论补充waitForFinished()。遗憾的是,QProcess 终止仍然没有正确关闭,分段错误发生在waitForStarted()或如下所示start() itself.

#0  0x00007f25e03a492a in QEventDispatcherUNIX::registerSocketNotifier () from /usr/local/Trolltech/Qt-4.7.4/lib/libQtCore.so.4
#1  0x00007f25e0392d0b in QSocketNotifier::QSocketNotifier () from /usr/local/Trolltech/Qt-4.7.4/lib/libQtCore.so.4
#2  0x00007f25e0350bf8 in ?? () from /usr/local/Trolltech/Qt-4.7.4/lib/libQtCore.so.4
#3  0x00007f25e03513ef in ?? () from /usr/local/Trolltech/Qt-4.7.4/lib/libQtCore.so.4
#4  0x00007f25e03115da in QProcess::start () from /usr/local/Trolltech/Qt-4.7.4/lib/libQtCore.so.4
#5  0x0000000000428628 in DbManager::extCmd()
#6  0x000000000042ca06 in DbManager::storePos ()
#7  0x000000000044f51c in DeviceConnection::incomingData ()
#8  0x00000000004600fb in DeviceConnection::qt_metacall ()
#9  0x00007f25e0388782 in QObject::event () from /usr/local/Trolltech/Qt-4.7.4/lib/libQtCore.so.4
#10 0x00007f25e0376e3f in QCoreApplicationPrivate::notify_helper () from /usr/local/Trolltech/Qt-4.7.4/lib/libQtCore.so.4
#11 0x00007f25e0376e86 in QCoreApplication::notify () from /usr/local/Trolltech/Qt-4.7.4/lib/libQtCore.so.4
#12 0x00007f25e0376ba4 in QCoreApplication::notifyInternal () from /usr/local/Trolltech/Qt-4.7.4/lib/libQtCore.so.4
#13 0x00007f25e0377901 in QCoreApplicationPrivate::sendPostedEvents () from /usr/local/Trolltech/Qt-4.7.4/lib/libQtCore.so.4
#14 0x00007f25e03a4500 in QEventDispatcherUNIX::processEvents () from /usr/local/Trolltech/Qt-4.7.4/lib/libQtCore.so.4
#15 0x00007f25e0375e15 in QEventLoop::processEvents () from /usr/local/Trolltech/Qt-4.7.4/lib/libQtCore.so.4
#16 0x00007f25e0376066 in QEventLoop::exec () from /usr/local/Trolltech/Qt-4.7.4/lib/libQtCore.so.4
#17 0x00007f25e0277715 in QThread::exec () from /usr/local/Trolltech/Qt-4.7.4/lib/libQtCore.so.4
#18 0x00007f25e027a596 in ?? () from /usr/local/Trolltech/Qt-4.7.4/lib/libQtCore.so.4
#19 0x00007f25df9b43f7 in start_thread () from /lib/libpthread.so.0
#20 0x00007f25def89b4d in clone () from /lib/libc.so.6
#21 0x0000000000000000 in ?? ()

附录 C:调试输出向我显示了错误消息:QProcess:进程仍在运行时被销毁。总是出现,当整理失败出现输出。这意味着我保护 QProcess 的锁定或/和终止尝试失败。 我想知道的问题:

a)如果创建一个 QProcess 对象并启动它,是我的extCmdProcessLock解锁?我已经尝试过使用正常的lock()调用而不是QMutexLoader但没有运气。

b) 文档说主线程如果我以这种方式使用 QProcess 将被停止。他们的意思真的是主线程 or the QProcess 启动的线程?我假设第二。

c) QProcess 不能在多线程环境中使用吗?如果两个线程创建一个 QProcess 对象并运行它,它们会互相干扰吗?也许该对象在某种程度上是静态的?

感谢您在填补知识漏洞方面的任何帮助。我真的希望能够解决这个难题。

附录 D:从任何线程中删除任何删除和deleteLater()后,我的QProcess仍然被破坏。

#0  0x00007fc94e9796b0 in QProcess::setProcessState () from /usr/local/Trolltech/Qt-4.7.4/lib/libQtCore.so.4
#1  0x00007fc94e97998b in QProcess::waitForStarted () from /usr/local/Trolltech/Qt-4.7.4/lib/libQtCore.so.4
#2  0x00007fc94e979a12 in QProcess::waitForFinished () from /usr/local/Trolltech/Qt-4.7.4/lib/libQtCore.so.4
#3  0x0000000000425681 in DbManager::extCmd()
#4  0x0000000000426fb6 in DbManager::storePos ()
#5  0x000000000044d51c in DeviceConnection::incomingData ()
#6  0x000000000045fb7b in DeviceConnection::qt_metacall ()
#7  0x00007fc94e9f4782 in QObject::event () from /usr/local/Trolltech/Qt-4.7.4/lib/libQtCore.so.4
#8  0x00007fc94e9e2e3f in QCoreApplicationPrivate::notify_helper () from /usr/local/Trolltech/Qt-4.7.4/lib/libQtCore.so.4
#9  0x00007fc94e9e2e86 in QCoreApplication::notify () from /usr/local/Trolltech/Qt-4.7.4/lib/libQtCore.so.4
#10 0x00007fc94e9e2ba4 in QCoreApplication::notifyInternal () from /usr/local/Trolltech/Qt-4.7.4/lib/libQtCore.so.4
#11 0x00007fc94e9e3901 in QCoreApplicationPrivate::sendPostedEvents () from /usr/local/Trolltech/Qt-4.7.4/lib/libQtCore.so.4
#12 0x00007fc94ea10500 in QEventDispatcherUNIX::processEvents () from /usr/local/Trolltech/Qt-4.7.4/lib/libQtCore.so.4
#13 0x00007fc94e9e1e15 in QEventLoop::processEvents () from /usr/local/Trolltech/Qt-4.7.4/lib/libQtCore.so.4
#14 0x00007fc94e9e2066 in QEventLoop::exec () from /usr/local/Trolltech/Qt-4.7.4/lib/libQtCore.so.4
#15 0x00007fc94e8e3715 in QThread::exec () from /usr/local/Trolltech/Qt-4.7.4/lib/libQtCore.so.4
#16 0x00007fc94e8e6596 in ?? () from /usr/local/Trolltech/Qt-4.7.4/lib/libQtCore.so.4
#17 0x00007fc94e0203f7 in start_thread () from /lib/libpthread.so.0
#18 0x00007fc94d5f5b4d in clone () from /lib/libc.so.6
#19 0x0000000000000000 in ?? ()

使用 QThread 来管理正在运行的进程是一种非常糟糕的方式。我一次又一次地看到它,这是对如何正确编写异步应用程序的一些基本误解。进程与您自己的应用程序是分开的。 QProcess 提供了一组漂亮的信号来通知您它何时成功启动、启动失败和完成。只需将这些信号挂接到您的 QObject 派生类的实例中的插槽中,您就可以完成所有设置。

如果应用程序中的线程数量明显超过平台上可用的核心/超线程数量,或者线程数量与某些不相关的运行时因素(例如正在运行的子进程的数量)相关联,那么这就是糟糕的设计。

看看我的另一个其他答案.

您可以在堆上创建 QProcess,作为监视 QObject 的子级。您可以将 QProcess 的finished() 信号连接到它自己的deleteLater() 槽,这样它就会在完成后自动删除自己。当监控 QObject 自身被破坏(例如应用程序关闭)时,它应该强制终止任何剩余的正在运行的进程。

更进一步的问题是如何执行不受控制的长时间运行的函数,例如没有异步 API 的数据库查询,当散布有良好的异步 API(例如 QProcess)时,影响最小。

一种规范的方法是:在必须的地方同步做事,否则异步做事。您可以通过调用其来停止控制对象以及任何正在运行的进程deleteLater()slot——通过信号/槽连接,或者使用QMetaObject::invokeMethod()如果您想在安全跨越线程边界的同时直接执行此操作。这是使用尽可能少的阻塞调用的主要好处:您可以对处理进行一些控制,并且可以在某些时候停止它。对于纯粹的阻塞实现,除了使用一些标志变量并在代码中进行测试之外,没有办法阻止它。

The deleteLater()每当事件循环可以在 QObject 所在的线程中旋转时就会得到处理。这意味着它将在数据库查询调用之间获得机会——事实上,在进程运行的任何时候。

未经测试的代码:

class Query : public QObject
{
  Q_OBJECT
public:
  Query(QObject * parent = 0) : QObject(parent) {
    connect(process, SIGNAL(error(QProcess::ProcessError)), SLOT(error()));
    connect(process, SIGNAL(finished(int,QProcess::ExitStatus)), SLOT(finished(int,QProcess::ExitStatus)));
  }
  ~Query() { process.kill(); }
  void start() {
    QTimer::singleShot(0, this, SLOT(slot1()));
  }
protected slots:
  void slot1() {
    // do a database query
    process.start(....);
    next = &Query::slot2;
  }
protected:
  // slot2 and slot3 don't have to be slots
  void slot2() {
    if (result == Error) {...}
    else {...}
    // another database query
    process.start(...); // yet another process gets fired
    next = &Query::slot3;
  }
  void slot3() {
    if (result == Error) {...}
    deleteLater();
  }

protected slots:
  void error() {
    result = Error;
    (this->*next)();
  }
  void finished(int code, QProcess::ExitStatus status) {
    result = Finished;
    exitCode = code;
    exitStatus = status;
    (this->*next)();
  }
private:
  QProcess process; 
  enum { Error, Finished } result;
  int exitCode;
  QProcess::ExitStatus exitStatus;
  void (Query::* next)();
};

就我个人而言,我会检查您使用的数据库是否有异步 API。如果没有,但如果客户端库有可用的源,那么我会做一个最小的端口来使用 Qt 的网络堆栈来使其异步。它会降低开销,因为每个数据库连接不再有一个线程,并且当您接近 CPU 饱和时,开销不会增加:通常,要使 CPU 饱和,您需要很多很多线程,因为它们大多闲置。使用异步接口,上下文切换的数量将会减少,因为线程将处理来自数据库的一个数据包,并且可以立即处理来自不同连接的另一个数据包,而无需进行上下文切换:执行保持在该线程的事件循环。

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

终止正在 Q​​Thread 内运行的正在进行的 QProcess? [复制] 的相关文章

  • 如何避免 Java 中的忙旋转

    我有一个多线程应用程序 其中一个线程向另一个线程发送消息 等待线程轮询消息并做出反应 处理锁 像这样 等待线程代码 while true if helloArrived System out println Got hello if bye
  • 如何在Qt中更快地读取数据?

    Qt读取数据库比C 慢吗 我想我错过了一些东西 为了比较阅读速度 我在 Qt 中编写了以下内容 QElapsedTimer t t start int count 0 QString cs Driver SQL Server Server
  • 使用 pthread_cond_signal 优雅地终止线程被证明是有问题的

    我需要发射一堆线程 并希望优雅地将它们拉下来 我正在尝试使用pthread cond signal pthread cond wait实现这一目标 但遇到了问题 这是我的代码 首先是thread main static void thrma
  • 如何将命令输出作为多个参数传递给另一个命令

    我想将命令的每个输出作为多个参数传递给第二个命令 例如 grep pattern input returns file1 file2 file3 我想复制这些输出 例如 cp file1 file1 bac cp file2 file2 b
  • BeagleBone Black 如何用作大容量存储设备?

    是否可以使用 BB 作为大容量存储设备 我希望将其连接到可以从 USB 连接 例如 USB 闪存驱动器 读取文件的音频播放器并充当包含一个特定文件夹的数据存储设备 及其子文件夹 从文件系统 如果可能 在连接到开发板的闪存驱动器上 正如设备规
  • grep 彩色线条

    我编写了一个简单的 PHP shell 脚本 它解析文件并输出某些元素 它产生大量的输出 采用不同的 bash 颜色 绿色表示正常 黄色表示警告 红色表示错误等 在开发过程中我想过滤掉一些行 例如 所有包含红色文本的行 我可以使用grep
  • 提升::亚洲。消息是在哪个线程中发送的?

    我试图了解内部工作boost asio图书馆 这真的很棒 我编写了一个简单的客户端 用于向服务器发送一条消息 问题是 它真正在哪个线程中发送消息 自从我使用async write 方法 调用后立即返回并且不发送任何内容 我已经评论了io s
  • 在 MacOS 上构建需要 net461 的 dotnet SDK 项目的最简单方法

    我有一个 dotnet SDK sln and a build proj with
  • SQLite同时读写

    我读过很多主题 但无法找到问题的答案 是否可以同时读写 我有后台线程更新一些数据 UI 需要存储在数据库中的一小部分数据 所以在UI线程中执行SELECT操作 但当更新正在进行时它会阻塞 结果 UI 冻结了几秒钟 有人在写入时成功从数据库读
  • 如何使用样式表删除 QWizard 中的水平线?

    我正在研究一个样式表QWizard我想删除按钮上方的水平线 我已经发布了一个最小的例子here https stackoverflow com q 52538669 8570451 这个问题是由scopchanov从最小的例子中解决的 但是
  • 如何在 Ubuntu/Linux 发行版中安装 Tesseract-OCR 3.03?

    我和一个朋友有兴趣为 CV 项目训练 tesseract OCR 引擎 我们尝试使用一些包装器 例如 PyTesser 和 pyocr 但结果目前不如我们需要的那么准确 因此 我们希望尝试训练超立方体以更好地实现我们的目的 即识别食品标签上
  • 使用 Python 将阿拉伯语或任何从右到左书写系统的字符串打印到 Linux 终端

    非常简单的例子是 city print city 我期望输出是 但实际上输出是相反的字符串 字母看起来有点不同 因为它们有开始 中间和结束形式 我无法将其粘贴到此处 因为复制粘贴会再次更正字符串的顺序 如何在 Linux 终端上正确打印阿拉
  • UI 线程正在阻塞调用 COM 对象的后台线程

    我正在开发一个通过第三方 COM 库与外部设备通信的应用程序 我试图让与设备的所有通信都通过后台线程 以防止通信问题搞砸我的应用程序 并消除在 UI 线程中进行通信所引入的一些其他复杂性 问题是 每当发生导致主 UI 线程阻塞的情况 即调用
  • 使用信号和槽更新指针

    我对 Qt 很陌生 请帮我解决这个问题 我正在使用线程在后台执行密集操作 同时我想更新 UI 所以我使用 SIGNALS 和 SLOTS 为了更新 UI 我发出一个信号并更新 UI 让我们考虑下面的示例代码 struct sample QS
  • 线程池的 lambda 函数内的编译器错误变量“未捕获”

    我正在学习 C 中的多线程 并尝试设置线程池 但收到编译器错误 提示 错误 未捕获 mapperNodes 和 错误 未捕获 command 我读过一些关于使用 this 捕获 lambda 中的变量的内容 但到目前为止没有任何效果 如何在
  • 在 Windows / Linux 中创建 Mac 包

    我自己努力制作一个 r 包 我按照 stackoverflow 中上一个问题的说明进行操作如何为外行开发软件包 http cran r project org bin windows Rtools 以下是我根据上一个问题采取的步骤 在新的
  • PHP mail() 函数不发送邮件

    我有一个小问题 我正在使用一个工作脚本 在我的测试帐户 共享服务器上工作 使用 mail 函数通过 PHP 发送邮件 我刚刚得到了一个专用服务器 但我还无法让该功能发挥作用 在过去的 10 个小时左右的时间里 我阅读了有关 BIND 用于
  • M:N线程模型真的利用了CPU核心吗?

    有几种线程模型可用于在应用程序中调度线程 1 1 内核级线程 用户创建的每个线程都映射到内核中的调度线程 N 1 用户级线程 用户在单个应用程序中创建的所有线程实际上都映射到单个调度的内核线程 M N 混合螺纹 用户在应用程序中创建的 M
  • Swift 对异步编程有什么语言级别的支持(如果有)?

    当应用程序必须通过不可预测的网络 例如智能手机应用程序 进行通信时 异步编程对于响应式用户界面来说是必须的 用户界面必须保持响应 同时等待结果从互联网上某处的服务器返回 在大多数语言中 应用程序程序员必须实现自己的状态机 可能使用闭包 来响
  • 优化 Keras 以使用所有可用的 CPU 资源

    好吧 我真的不知道我在说什么 所以请耐心听我说 我正在使用 Theano 后端运行 Keras 以在 MNIST 图像上运行基本的神经网络 目前只是一个教程 过去 我一直使用我的旧 HP 笔记本电脑 因为我有 Windows 和 Ubunt

随机推荐

  • HTML WebSocket 是否为每个客户端维护一个开放连接?这个有规模吗?

    我很好奇是否有人有关于 HTML WebSockets 可扩展性的任何信息 对于我读到的所有内容 似乎每个客户端都会与服务器保持开放的通信线路 我只是想知道它是如何扩展的以及服务器可以处理多少个打开的 WebSocket 连接 也许让这些连
  • Java 中如何找到给定类的所有子类?

    在 Java 中 如何尝试查找给定类的所有子类 或给定接口的所有实现者 到目前为止 我有一种方法可以做到这一点 但我发现它效率很低 至少可以说 方法是 获取类路径上存在的所有类名的列表 加载每个类并测试它是否是所需类或接口的子类或实现者 在
  • 不使用 gethostbyname 从 DNS 获取 IP?

    PHP s 获取主机名 就超时而言 函数似乎不可配置 我想将 DNS 请求限制为 1 秒或更短 因为再多的请求就会显示问题并应被忽略 那么 有没有一种方法可以使用套接字或 cURL 来进行 DNS 查询呢 我能够使用 PHP 流发出 SMT
  • 如何恢复 JavaFX TableColumn 的 onEditCommit 中的先前值?

    我有一个用 JavaFX 编写的表 用户可以选择编辑其中一列 当对单元格进行编辑时 我尝试根据新文本重命名一些内部对象 如果重命名失败 我会发出通知并弹出错误对话框 然后我想将原始文本恢复到该字段中 由于某种原因 这让我陷入了错误弹出窗口的
  • 在 bash 脚本中使用“备用屏幕”

    The 备用屏幕被许多 用户交互 终端应用程序使用 如 vim htop screen alsamixer less 它就像终端内容的不同缓冲区 当应用程序退出时它会消失 因此整个终端会恢复并看起来应用程序没有输出任何内容 我想在我自己的
  • REST - HTTP 状态 405 - 不允许的方法

    我尝试在我的网络项目上使用 REST POST 有效 但 DELETE 和 PUT 不起作用 我会看到错误 HTTP 状态 405 不允许方法 并且 GET 根本不起作用 id RFC 2068 中未定义 且 Servlet API 不支持
  • C# .Net 中 XmlElement 中的空白

    XmlElement child doc CreateElement element Where doc是一个对象XmlDocument 当代码执行上面一行时element Tom and Jerry 我收到以下错误 The charact
  • Woocommerce 中的本地取货运输选项自定义百分比折扣

    我的 WooCommerce 结帐页面提供了一些运输选项 统一费率 需要花钱 本地取货 免费 如果客户选择本地取货运输方式 我如何才能获得订单总成本 5 的折扣 以下代码将为购物车小计添加 5 的折扣当地取货选择的运输方式 add acti
  • UWP 中的 Process.Start

    我想从我的 UWP 应用程序运行文件 视频 音乐 图片 对于 WPF 我可以使用Process Start path 方法 但此方法现在可用于 UWP 我发现我可能应该使用FullTrustProcessLauncher https lea
  • 在 ForEach-Object -Parallel 块内从自身递归调用函数 - 并行块内无法识别函数

    第一次在这里提问 请善待 我试图以并行方式递归地获取所有目录 希望减少遍历驱动器所需的时间 下面是我尝试过的代码 本质上我想要做的是输入一个文件夹 并对其子文件夹及其子文件夹等并行执行相同的操作 但该函数在并行块内无法识别 function
  • 用颜色向量突出显示 ggplot2 中的前 3 个

    我有下面的代码 我想用选定的颜色为前 3 个着色 提前谢谢了 library ggplot2 library dplyr df lt data frame dose c D0 5 D1 D2 D3 D4 D5 len c 4 2 10 29
  • 从Python字典中删除重复的键但对值求和

    我有一本Python字典 d tags 0 value tags 1 value tags 2 value tags 3 value tags 4 value 想象一下这个字典大了 10 倍 它有 50 个键和 50 个值 在此标签中可以找
  • 空 DataTable 到 Json 并包含列名称

    我的应用程序分为两部分 客户端和服务器 服务器端询问 SQL 数据库并将结果存储在 DataTable 中 然后我使用下一个函数将 DataTable 转换为 Json 以将其发送到客户端 问题是当没有结果时 我得到一个空字符串 我想得到一
  • 如何在 Neo4j 3.0.1 中配置查询超时

    我想设置查询超时neo4j conf对于 Neo4j 3 0 1 任何花费超过超时时间的查询都应该被终止 我主要关心的是为来自 Neo4j 浏览器的查询设置超时 看起来像这是可能的过去与 execution guard enabled tr
  • OpenCV:相对于参考图像移动/对齐面部图像(图像配准)

    我是 OpenCV2 的新手 正在从事情感识别项目 希望将面部图像与参考面部图像对齐 我希望在进行旋转之前先进行图像翻译 当前的想法是在 x 和 y 坐标的有限范围内运行搜索 并使用平方差之和作为误差度量来选择最佳的 x y 参数来对齐图像
  • PHP 将 24 位颜色转换为 4 位颜色

    背景 我正在将图像转换为 ascii 艺术 这可以完美地工作 甚至可以使用 24 位颜色 将颜色转换为正确的 RGB 值 然而 我现在想用 4 位调色板而不是 24 位来渲染 ASCII 艺术 如何使用 PHP 将 24 位颜色转换为 4
  • 添加到 Woocommerce 的自定义元数据未显示在订单项元中

    我有一个 WooCommerce 订单的自定义元数据 现在我想在结账后将其显示在感谢页面上 但是该数据不可用 数据已保存并可在管理员中使用 但我似乎无法访问它 function custom order item meta item id
  • oData $expand 派生类型

    我在使用 odata 查询获取派生类型时遇到挑战 Url odata resource expand 衍生类型 看到这个link这给出了像这样的选项 People OfType Employee 41 Manager 或 People Em
  • 无法使用 AngularJS 在 Android 浏览器中执行 POST 请求

    我有一个有角度的应用程序 可以显示记录 并让用户能够添加记录 在桌面或 iOS 设备上一切正常 但在 Android 设备上 POST 方法失败 403 禁止 这是我的服务中的代码 obj getRecords function retur
  • 终止正在 Q​​Thread 内运行的正在进行的 QProcess? [复制]

    这个问题在这里已经有答案了 如何终止正在 Q Thread 内运行并被另一个 QThread 删除的正在进行的 QProcess 我什至插入了一个 QMutex extCmdProcessLock 这应该避免在 extCmdProcess