Курс по Raku / Функционално, паралелно, реактивно и уеб програмиране / Паралелно програмиране / Канали

Четене след края

Какво става, ако извикате .receive повече пъти, отколкото има стойности за взимане? Отговорът зависи от това дали каналът е затворен.

Вземете примера с производител и потребител отпреди: фонова задача изпраща три стойности и затваря канала. Ами ако потребителят поиска четвърта?

my $c = Channel.new;
start {
    $c.send($_) for 1..3;
    $c.close;
}

say $c.receive; # 1
say $c.receive; # 2
say $c.receive; # 3
say $c.receive; # с едно получаване повече

При затворен канал излишното получаване хвърля изключение

Затварянето не изхвърля вече наредените стойности — трите извиквания на .receive по-горе пак връщат 1, 2 и 3. Но щом каналът е затворен и празен, повече стойности никога няма да пристигнат, така че вместо да ви остави да чакате вечно, Raku повдига изключение:

Cannot receive a message on a closed channel

Изключението е X::Channel::ReceiveOnClosed. Това е по-скоро полезно, отколкото досадно: то недвусмислено казва на потребителя, че е изчерпал канала. На практика изобщо не стигате до него, ако консумирате с .list (който спира чисто при затварянето) или ако въртите цикъл само докато има стойности — и двата начина са показани на предишната страница.

При отворен канал излишното получаване блокира

Ако производителят никога не затвори канала, .receive няма как да разбере дали ще дойде още една стойност, така че просто чака:

my $c = Channel.new;
$c.send(1);
say $c.receive; # 1
say $c.receive; # чака тук — каналът е отворен, но празен

Програмата увисва на второто .receive, защото стойност може още да бъде изпратена. Точно за тази опасност предупреждаваше предишната страница: забравите ли .close, обикновеното „изчакай следващата стойност“ се превръща в чакане без край.

Така двата изхода са противоположни по полезен начин. Затвореният канал се проваля бързо, когато е празен — получавате изключение, което се вижда и може да се прихване. Отвореният канал продължава да чака — точно каквото трябва, докато производителят още работи, но мълчаливо увисване, ако производителят тихо е спрял, без да затвори. Затварянето на канала е именно онова, което превръща това мълчаливо увисване в ясен сигнал, че потокът е приключил.

Практика

Направете 1 тест върху съдържанието на тази тема.

Навигация в курса

Тест — Затваряне на канал   |   Тест — Четене след края


💪 Или преминете направо към упражненията в този раздел.