Raku의 다른 스레드에서 발생한 오류를 어떻게 전파하고 포착 할 수 있습니까?


9

별도의 스레드에서 오류를 전파하는 가장 좋은 방법은 무엇입니까 (예 : 시작 블록, Proc :: Async 또는 이들을 포함하는 하위). try / CATCH 블록에서 새 스레드를 분리하는 코드를 래핑하는 것만으로는 작동하지 않으며 await를 사용하면 하위 루틴의 반환 값에 따라 작동합니다 (즉, 하위 반환 자체는 await 접근 방식에서는 작동하지 않음).


어쩌면 foobar여기에 제거 할 수 있습니까?
jjmerelo

1
이 시나리오에 여전히 문제가 있습니다 ... Raku에서는 불가능하며 실제 클래스를 재구성해야합니까? 다른 곳에서 재사용 할 수있는 클래스에서 응용 프로그램 특정 오류 처리를 원하지 않기 때문에 이상적이지 않습니다.
ryn1x

@ ryn1x이 질문을 원래 형태로 복원하는 것이 좋습니다. 그런 다음 시작 부분에 일부 답변이 귀하의 질문 본문에 주어진 문제 진술을 해결했지만 실제로 더 일반적인 것을 찾고 있다고 설명하는 메모를 추가하십시오. 또한 귀하가 수락 한 답변이 더 일반적이지만 그 이후로는 여전히 일반적이지 않다는 결론을 내 렸습니다. 또한, 당신은 현상금을 시도하여 더 많은 일반성을 요구했지만 도움이되지 않았습니다. 그런 다음 문제를 설명하는 예를 들어이 질문에 다시 연결 하여 질문을 작성하십시오 .
raiph

현재의 대답은 나에게 충분합니다. 질문이 너무 길고 여기에 끝나는 사람에게는 구체적이기 때문에 질문을 변경했습니다.
ryn1x

답변:


6

사용하다 await .

예를 들어, 코드에서 다음 세 줄을 바꾸십시오.

foo;
bar;
baz;

와:

await foo, bar, baz;

이것은 작동하지만 foo, bar 및 baz는 실제로 자체를 반환하는 메서드이기 때문에 실제 문제로 확장되지 않았습니다. 질문과 예제를 업데이트했습니다.
ryn1x

5

이론적으로 그 코드 는 죽어야한다 .

6.d 버전의 언어에서 싱크 컨텍스트에 사용 된 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";

당신의 프로그램은 죽지 않기 때문에 두 번째 상황에 있다고 말할 것입니다. 어떤 이유로 든 침몰하지 않습니다. 그러나 어떤 상황이든 솔루션은 동일합니다. 동일한 코드 블록 내에서 예외를 잡아야합니다.

해결책 : await주변 코드가 죽을 수 있도록 약속 (싱크되지 않음) 또는 변수에 할당하십시오. 그러나 OP에 응답하면 아니요. 다른 블록에서 예외를 잡을 수없는 것과 같은 방식으로 다른 스레드에서 예외를 잡을 수 없습니다.


이 모든 것에 감사드립니다. 실제로 내 영업소보다 더 구체적이어야합니다. 싱크 컨텍스트에서 호출하지 않고 OP의 함수가 실제로 자체를 반환하는 메서드이므로 대기 솔루션도 작동하지 않습니다. 질문과 예제를 업데이트했습니다.
ryn1x

4

채널을 사용하여 이동 루틴에서 오류를 전달하기 위해 Go에 사용 된 규칙에 따라 Raku에서도 동일한 접근 방식을 찾았습니다. 채널을 사용하여 메인 스레드에서 처리 할 비동기 코드에서 오류를 보낼 수 있습니다.

예:

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;
당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.