Raku'daki başka bir iş parçacığında atılan hataları nasıl çoğaltabilir ve yakalayabilirim?


9

Hataları ayrı bir iş parçacığından yaymanın en iyi yolu nedir (örn. Start bloğu, Proc :: Async veya bunları içeren alt). Yeni bir iş parçacığını döndüren kodu basitçe bir try / CATCH bloğuna sarmak işe yaramaz ve beklemenin kullanılması sadece alt rutinin dönüş değerine bağlı olarak çalışır (yani bir alt geri dönen benlik beklemek yaklaşımıyla çalışmaz).


Belki foove barburada elimine edilebilir?
jjmerelo

1
Hala bu senaryo ile ilgili sorunlar yaşıyorum ... Raku'da bu mümkün değil ve gerçek sınıfların yeniden yapılandırılmasını gerektiriyor mu? Başka bir yerde yeniden kullanılabilir sınıflarda uygulamaya özgü hata işleme istemiyorum çünkü bu ideal olmaz ...
ryn1x

@ ryn1x Bu soruyu orijinal haliyle geri yüklemeyi düşünmenizi öneririm. Daha sonra başlangıçta, yanıtlarımızdan bazılarının sorunuzun gövdesinde verilen sorun ifadesini çözmesine rağmen, aslında daha genel bir şey aradığınızı açıklayan bir not ekleyin. Dahası, kabul ettiğiniz cevap daha genel olsa da, o zamandan beri hala yeterince genel olmadığı sonucuna vardınız. Ayrıca, daha fazla genellik istemekle bir ödül vermeyi denediniz, ancak bu yardımcı olmadı. Ardından , soruyu yeniden ortaya koyduğuna inandığınız bir örnekle bu soruya tekrar bağlayarak yeni bir soru yazın.
raiph

Şimdiki cevap benim için tamamen yeterli. Soruyu değiştirdim, çünkü burada biten herkes için çok uzun ve spesifik hale geliyordu.
ryn1x

Yanıtlar:


6

Kullanın await.

Örneğin, kodunuzdaki şu üç satırı değiştirin:

foo;
bar;
baz;

ile:

await foo, bar, baz;

Bu işe yarıyor ama asıl sorunuma göre ölçeklenmedi çünkü foo, bar ve baz aslında kendini döndüren yöntemlerdir. Soruyu ve örneği güncelledim.
ryn1x

5

Teorik olarak, bu kod ölmelidir :

Dilin 6. d sürümünden itibaren, lavabo bağlamında kullanılan start deyimi öneki otomatik olarak bir istisna işleyici ekleyecektir. Verilen kodda bir istisna oluşursa, yazdırılır ve program, herhangi bir start deyimi öneki olmadan atılmış gibi çıkar.

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 

Bu durumda bu garip bir durumdur çünkü sözünü batırmıyorsunuz (iade ediyorsunuz), ama sonunda batırdınız çünkü boş bağlamda çalıştırıyorsunuz.

Aynı belgeler size çözüm sunar: içeriği batırmayın:

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

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

Programınız ölmediği için ikinci durumda olduğunuzu söyleyebilirim. Bazı nedenlerden dolayı battı değil. Ancak durum ne olursa olsun, çözüm aynıdır: istisnayı aynı kod bloğu içinde yakalamanız gerekir.

Çözüm: awaitvaat (onu batırmayacak) veya bir değişkene atar, böylece çevredeki kod da ölür. Ancak OP'nize yanıt verirseniz, hayır, başka bir iş parçacığından bir istisna yakalayamazsınız, aynı şekilde başka bir bloktan bir istisna yakalayamazsınız.


Tüm bunlar için teşekkürler. Aslında OP'mdekinden daha spesifik olmam gerekiyor. Lavabo bağlamında çağırmıyorum ve beklemek çözüm de çalışmıyor çünkü OP fonksiyonları aslında kendini döndüren yöntemler. Soruyu ve örneği güncelledim.
ryn1x

4

Go'yu kanallar kullanarak gitme rutinlerinden geçirmek için kullanılan sözleşmenin ardından Raku'da çalışmak için aynı yaklaşımı buldum. Ana iş parçacığı tarafından işlenecek eşzamansız koddan hata göndermek için bir Kanal kullanılabilir.

Misal:

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;
Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.