ฉันจะเผยแพร่และจับข้อผิดพลาดที่ถูกโยนในเธรดอื่นใน Raku ได้อย่างไร?


9

วิธีที่ดีที่สุดในการเผยแพร่ข้อผิดพลาดจากเธรดแยกต่างหากคือ (เช่น start block, Proc :: Async หรือ sub ที่ประกอบด้วยสิ่งเหล่านี้) เพียงแค่ห่อโค้ดที่หมุนเธรดใหม่ในบล็อก try / CATCH แล้วไม่ทำงานและการใช้ waitit จะใช้ได้เฉพาะขึ้นอยู่กับค่าส่งคืนของรูทีนย่อย


อาจfooและbarสามารถถูกกำจัดได้ที่นี่?
jjmerelo

1
ฉันยังคงมีปัญหากับสถานการณ์นี้ ... มันเป็นไปไม่ได้ใน Raku และต้องการปรับโครงสร้างคลาสจริงหรือไม่? จะไม่เหมาะเพราะฉันไม่ต้องการการจัดการข้อผิดพลาดเฉพาะแอปพลิเคชันในชั้นเรียนที่สามารถนำมาใช้อีกที่อื่น ...
ryn1x

@ ryn1x ฉันขอแนะนำให้คุณลองกู้คืนคำถามนี้กลับไปเป็นรูปแบบเดิม จากนั้นเพิ่มบันทึกย่อเมื่อเริ่มต้นอธิบายว่าแม้ว่าคำตอบบางส่วนของเราจะแก้ไขคำแถลงปัญหาที่ให้ไว้ในเนื้อหาของคำถามของคุณคุณกำลังมองหาบางสิ่งที่กว้างกว่า ยิ่งไปกว่านั้นแม้ว่าคำตอบที่คุณยอมรับนั้นกว้างกว่า แต่ก่อนคุณได้ข้อสรุปว่ามันยังไม่กว้างพอ นอกจากนี้คุณลองรับรางวัลควบคู่ไปกับการขอความช่วยเหลือเพิ่มเติม แต่ก็ไม่ได้ช่วยอะไร จากนั้นเขียนคำถามใหม่เชื่อมโยงกลับไปที่ตัวอย่างนี้ด้วยตัวอย่างที่คุณเชื่อว่าจะแสดงปัญหา
raiph

คำตอบปัจจุบันเพียงพอสำหรับฉันอย่างสมบูรณ์ ฉันเปลี่ยนคำถามเพราะมันยาวเกินไปและเฉพาะเจาะจงสำหรับทุกคนที่ลงเอยที่นี่
ryn1x

คำตอบ:


6

awaitใช้

ตัวอย่างเช่นแทนที่ทั้งสามบรรทัดในรหัสของคุณ:

foo;
bar;
baz;

ด้วย:

await foo, bar, baz;

ใช้งานได้ แต่ไม่ได้ปรับให้เข้ากับปัญหาจริงของฉันเพราะ foo, bar และ baz เป็นวิธีการที่คืนกลับมาเอง ฉันอัพเดตคำถามและตัวอย่าง
ryn1x

5

ในทางทฤษฎีรหัสนั้นควรตาย :

สำหรับภาษาเวอร์ชัน 6.d คำนำหน้าคำสั่งเริ่มต้นที่ใช้ในบริบท sink จะแนบตัวจัดการข้อยกเว้นโดยอัตโนมัติ หากมีข้อยกเว้นเกิดขึ้นในรหัสที่กำหนดมันจะถูกพิมพ์และโปรแกรมจะออกจากนั้นเหมือนกับว่ามันถูกโยนโดยไม่มีคำนำหน้าคำสั่งเริ่มต้นใด ๆ ที่เกี่ยวข้อง

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 ของฉัน ฉันไม่ได้โทรในบริบท sink และวิธีการแก้ปัญหาที่รอคอยก็ไม่ทำงานเพราะฟังก์ชั่นจาก 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.