windows - 如何在 Perl 中线程安全地设置 STDOUT 编码?

标签 windows multithreading perl encoding thread-safety

根据文档,使用 encoding 模块与 threads 不是线程安全的,并且自 perl 1.18 起已弃用。我在 Windows 7 机器上使用 perl 5.16。我需要将输出转换为 windows 866 编码。尝试运行线程时,以下代码解释器崩溃。

use utf8;
binmode(STDOUT, ':encoding(cp866)');
use threads;


my $thr = threads->create(sub {
    print "поток работает";
})->detach();

sleep 1;
print "основной поток также работает";

如果没有 binmode(STDOUT, ':cp866');,我会出现“打印中的宽字符”错误,并且文本以不正确的字符集显示。那么应该如何正确设置编码呢?

最佳答案

我在 Win7 上用 ActivePerl 5.16.3 x64 复制了这个问题

我能够通过升级到 ActivePerl 5.24.2 x64 来解决它。

清理代码:

use utf8;
use open ':std', ':encoding(cp866)';
use threads;

my $thr = async {
    print "поток работает";
};

print "основной поток также работает";
$thr->join();

解决方法:您可以手动编码而不是使用 PerlIO 层。

use utf8;
use threads;

use Encode qw( encode );

my $thr = async {
    print encode('cp866', "поток работает");
};

print encode('cp866', "основной поток также работает");
$thr->join();

解决方法:在每个线程中克隆 STDOUT,并将编码层应用于非共享克隆。

use utf8;
use threads;

my $thr = async {
    open(my $fh, '>&=:encoding(cp866)', \*STDOUT) or die $!;
    *STDOUT = $fh;

    print "поток работает";
};

open(my $fh, '>&=:encoding(cp866)', \*STDOUT) or die $!;
*STDOUT = $fh;

print "основной поток также работает";
$thr->join();

(这不会克隆底层文件描述符,因此更改非常透明。)

关于windows - 如何在 Perl 中线程安全地设置 STDOUT 编码?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/47519665/

相关文章:

perl - Mechanize 基本问题

Windows CRYPT32 CertFreeCertificateChainEngine 从受信任的根权限中删除用户证书

windows - IIS 用户目录,如 linux public_html

.net - 查找GUI控件的所有者线程

android - 观察由另一个线程修改的对象时 Android JUnit 测试中的计时问题

perl - 为什么 Perl 的 printf 会输出格式说明符而不是格式化数字?

perl - For 循环和词法范围的变量

python - Windows API "CreateWindowEx"能否在 Python (3.6.8) 64 位使用的 DLL 中工作?

windows - 在 Windows Phone 8 中从 MySQL 数据库绑定(bind) LongListSelector 中的字符串

java - 如何使 setContentView() 在线程中正常工作?