如何传播和捕获Raku中另一个线程抛出的错误?


9

从单独的线程传播错误的最佳方法是什么(例如,启动块,Proc :: Async或包含这些错误的子线程)。简单地将产生新线程的代码包装在try / CATCH块中是行不通的,而使用await仅取决于子例程的返回值(即,子返回self不适用于await方法)。


也许foobar可以在这里消除?
jjmerelo

1
我在这种情况下仍然有问题...在Raku中根本不可能吗,需要重新构造实际的类?那不是理想的,因为我不想在可以在其他地方重用的类中处理特定于应用程序的错误...
ryn1x

@ ryn1x我建议您考虑将这个问题恢复为原始形式。然后在开头添加一条注释,说明尽管我们的某些答案解决了问题正文中给出的问题说明,但实际上您正在寻求更通用的方法。此外,虽然您接受的答案比较笼统,但您得出的结论仍然不够笼统。此外,您尝试了赏金,并要求更多的通用性,但这无济于事。然后写一个问题,并链接到该问题,并举一个您认为确实可以说明问题的示例。
雷夫

当前的答案对我来说是完全足够的。我改变了这个问题,因为它变得太长了,而且对于最终到这里的人来说太具体了。
ryn1x

Answers:


6

使用await

例如,在代码中替换以下三行:

foo;
bar;
baz;

与:

await foo, bar, baz;

这行得通,但是并没有解决我的实际问题,因为foo,bar和baz实际上是返回self的方法。我更新了问题和示例。
ryn1x

5

从理论上讲,该代码应该消失

从语言的6.d版本开始,在接收器上下文中使用的start语句前缀将自动附加异常处理程序。如果给定代码中发生异常,它将被打印,然后程序将退出,就像抛出该异常而没有涉及任何start语句前缀一样。

use v6.c;
start { die }; sleep ⅓; say "hello"; # OUTPUT: «hello␤» 

use v6.d;
start { die }; sleep ⅓; say "hello";
# OUTPUT: 
# Unhandled exception in code scheduled on thread 4 
# Died 
#     in block  at -e line 1 

在这种情况下,这是一个奇怪的情况,因为您没有兑现承诺(您要兑现承诺),但最终您会兑现承诺,因为您是在无效上下文中运行它。

相同的文档为您提供了解决方案:不要沉浸上下文:

# Don't sink it: 
my $ = start { die }; sleep ⅓; say "hello"; # OUTPUT: «hello␤» 

# Catch yourself: 
start { die; CATCH { default { say "caught" } } };
sleep ⅓;
say "hello";

由于您的程序没有消失,我会说您处于第二种情况。由于某种原因,它不会下沉。但是无论如何,解决方案都是相同的:您需要在同一代码块内捕获异常。

解决方案:awaitpromise(不会沉没它)或将其分配给某个变量,以便周围的代码也死掉。但是响应您的OP,不,您不能从另一个线程捕获异常,就像您不能从另一个块捕获异常一样。


感谢所有这些。实际上,我需要比我的操作更具体。我没有在接收器上下文中调用,并且await解决方案也无法正常工作,因为OP中的函数实际上是返回self的方法。我更新了问题和示例。
ryn1x

4

按照Go中使用的惯例使用通道将错误传递出go例程之后,我发现了在Raku中使用相同的方法。可以使用Channel从要由主线程处理的异步代码中发送错误。

例:

my $errors = Channel.new;

my $err-supply = $errors.Supply;
$err-supply.tap(-> $e {say "handle error: $e"});

start {
    die "something went horribly wrong";

    CATCH {
        default {
            $errors.send($_);
        }
    }
}

sleep 1;
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.