【问题标题】:GPars forkOffChild exception handlingGPars forkOffChild 异常处理
【发布时间】:2012-12-13 23:51:55
【问题描述】:

我正在使用 GPars 的 fork/join。当我在调用 forkOffChild 后抛出异常时,它会被掩埋。

例如:

def myRecursiveClosure = { boolean top ->
    try {
        if (!top) {
            throw new RuntimeException('child had a problem')
        } else {
            forkOffChild(false)
        }
    } catch (Exception exc) {
        println 'Exception handled internally'
        throw exc
    }
}

try {
     GParsPool.withPool {
         GParsPool.runForkJoin(true, myRecursiveClosure)
    }
} catch (Exception exc) {
     println 'Exception handled externally'
     throw exc
}

在这里,我设置了一个标志,因此我知道闭包已被递归调用。然后,我抛出一个异常,它被“内部”捕获,但重新抛出从未被“外部”捕获。所以我不知道分叉的孩子失败了。

我也尝试了异常处理程序,但它似乎也没有被调用。

这是预期的行为,还是我做错了什么?有什么策略可以帮助解决这个问题吗?我不能让孩子默默地失败。

谢谢!

【问题讨论】:

    标签: groovy gpars


    【解决方案1】:

    这里的重要部分是 forkOffChild() 不会等待孩子运行。它只是安排它执行。因此,您不能指望 forkOffChild() 方法会从子级传播异常,因为它们很可能在父级从 forkOffChild() 方法返回很久之后才发生。

    然而,通常情况下,父级对子级计算的结果感兴趣,因此它会在分叉后的某个时间使用 getChildrenResults() 方法收集结果。这会返回一个计算值列表或重新抛出潜在的异常。

    此 sn-p 显示了获得预期行为的最小更改:

       try {
            if (!top) {
                throw new RuntimeException('child had a problem')
            } else {
                forkOffChild(false)
                println childrenResults
            }
        } catch (Exception exc) {
            println 'Exception handled internally'
            throw exc
        }
    

    【讨论】:

    • 谢谢!我看了你的例子,Vaclav,看到了这个。
    • 呃,那里超时了。你的解释很有道理。我试过了,它奏效了。我假设这也是异步函数的正确方法。测试后,我可以看到并行集合确实将它扔给调用者,我假设他们正在内部执行这种“获取结果”。他们似乎最终会死,我想没有什么好的方法可以立即杀死所有线程,但如果有一个异常?
    • 好吧,这里有一个相关的问题...... whenBound 不会像 get() 那样抛出异常,并且不会调用闭包代码。您如何使用异步函数和 whenBound 处理异常?如果您愿意,我将发布一个单独的问题。谢谢!
    • 是的,如果发生异常,并行收集不会取消正在进行的计算。
    • 一个异步函数会将异常绑定到返回的promise,因此get()会重新抛出它,whenBound()会将它传递给处理程序:result.whenBound{if (it instanceOf Exception) ... }
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多