使用 C++ 处理 Qt 脚本中的异常?

Posted

技术标签:

【中文标题】使用 C++ 处理 Qt 脚本中的异常?【英文标题】:Exception Handling in Qt Script with C++? 【发布时间】:2009-10-09 11:47:56 【问题描述】:

我有以下动作,当某个特定的时候执行 在Qt 应用程序中按下按钮:

#include <shape.h>

void computeOperations()

    polynomial_t p1("x^2-x*y+1"),p2("x^2+2*y-1");
    BoundingBox bx(-4.01, 4.01,-6.01,6.01,-6.01,6.01);
    Topology3d g(bx);
    AlgebraicCurve* cv= new AlgebraicCurve(p1,p2);
    g.push_back(cv);
    g.run();
    //Other operations on g.

Topology3d(...), AlgebraicCurve(..), BoundingBox(...), polynomial_t(...) 是在 对应的头文件。

现在对于 p1 和 p2 的某些值,g.run() 方法可以完美运行。

因此对于 p1 和 p2 的一些其他值,g.run() 不是 随着该方法以某种方式被阻塞并且 出现消息“应用程序无响应”,我必须 杀死应用程序。

我希望有以下行为:无论何时 g.run() 耗时太长,因某些特定原因被阻塞 p1, p2 的值,我想显示一个警告框 使用 QMessageBox::Warning。

我尝试用 try... 和 catch... 来做到这一点:

#include <shape.h>

class topologyException : public std::runtime_error

    public:
        topologyException::topologyException(): std::runtime_error( "topology fails" ) 
;

void computeOperations()

    try
    
        polynomial_t p1("x^2-x*y+1"),p2("x^2+2*y-1");
        BoundingBox bx(-4.01, 4.01,-6.01,6.01,-6.01,6.01);
        Topology3d g(bx);
        AlgebraicCurve* cv= new AlgebraicCurve(p1,p2);
        g.push_back(cv);
        g.run();
        //other operations on g
        throw topologyException();
    
    catch(topologyException& topException)
    
        QMessageBox errorBox;
        errorBox.setIcon(QMessageBox::Warning);
        errorBox.setText("The parameters are incorrect.");
        errorBox.setInformativeText("Please insert another polynomial.");
        errorBox.exec();
    

这段代码可以编译,但运行时并没有真正实现 实现所需的行为。

对于 g.run() 被阻止的多项式错误 永远不会达到消息框代码,加上多项式 对于哪个 g.run() 运行良好,错误消息框 代码仍然以某种方式到达,并且该框出现在 应用。

我是处理异常的新手,所以任何帮助都不仅仅是 欢迎。

我认为程序在 g.run() 中的某个地方被阻塞了,所以 它没有达到异常,我还是不明白 到底发生了什么。

我仍然想不去就抛出这个异常 进入 g.run() 的代码,这个函数被实现为 一个更大的库的一部分,我只是在我的代码中使用它。

我可以在我的程序中有这种行为而不添加任何内容吗 g.run() 函数中的 try... catch... 块语句?

【问题讨论】:

【参考方案1】:

使用 try-catch 无法达到您想要的效果。如果 g.run() 花费太多时间或进入无限循环,这并不意味着会抛出异常。

您可以做的是,您可以将需要大量时间的操作移到另一个线程中。在您的事件处理程序中启动该线程并等待它在您的主线程中完成一段固定的时间。如果它没有完成,请终止该线程并显示您的消息框。

如需进一步参考,请阅读QThread、Qt Thread Support

【讨论】:

【参考方案2】:

感谢您的建议。 所以我知道我应该如何创建线程,比如:

class myopThread : public QThread

public:
    void run();
;

然后我在重写run()函数,把所有耗时的操作都放在里面:

void myopThread::run()

    polynomial_t p1("x^2-x*y+1"),p2("x^2+2*y-1");
    BoundingBox bx(-4.01, 4.01,-6.01,6.01,-6.01,6.01);
    Topology3d g(bx);
    AlgebraicCurve* cv= new AlgebraicCurve(p1,p2);
    g.push_back(cv);
    g.run();
    //other operations on g

    exec();

好的,到目前为止一切都很清楚,但我仍然看不到如何“在事件处理程序中启动该线程并等待它在您的主线程中完成一段固定的时间。如果它没有完成,请杀死它线程并显示您的消息框。”

我的意思是在事件处理程序中启动线程以某种方式使用连接(..Signal,Slot..),但我不知道这是如何完成的。我以前从未使用过 QThread,所以它是新的。

非常感谢您的帮助, 玛达琳娜

【讨论】:

【参考方案3】:

据我所知,解决这个问题的最优雅的方法是使用未来值。如果您之前没有遇到过这些,那么在这种情况下它们会非常方便。假设您有一个稍后需要的值,但您可以同时开始计算。代码可能如下所示:

SomeValue getValue() 
    ... calculate the value ...


void foo() 
    Future<SomeValue> future_value(getValue);
    ... other code that takes a long time ...

    SomeValue v = future_value.get();

当然,在调用.get() 方法时,计算的值会被返回,要么通过当时调用该函数,要么通过检索在创建Future&lt;T&gt; 时启动的另一个线程中计算的缓存值。一件好事是,至少对于一些库,您可以将超时参数传递给.get() 方法。这样,如果您的值计算时间过长,您总是可以解除阻塞。如此优雅通常无法实现。

对于现实生活中的图书馆,您可以尝试查看记录在 here 的图书馆。我记得它没有被接受为官方的 boost 期货库,但它肯定有希望。祝你好运!

【讨论】:

以上是关于使用 C++ 处理 Qt 脚本中的异常?的主要内容,如果未能解决你的问题,请参考以下文章

处理主脚本中的自定义异常

Qt使用QJSEngine执行脚本

python脚本应用中的检测:处理异常和触发异常

c++异步回调函数引用传递空指针异常

使用 SqlPlus 执行 Oracle 脚本;如果有任何异常,在脚本处理之前进入状态

qt中的全局try and catch块