免費注冊 查看新帖 |

Chinaunix

  平臺 論壇 博客 文庫
最近訪問板塊 發新帖
查看: 5800 | 回復: 3
打印 上一主題 下一主題

[Perl]GUI顯示多線程任務進度 [復制鏈接]

論壇徽章:
12
子鼠
日期:2014-10-11 16:46:482016科比退役紀念章
日期:2018-03-16 10:24:0515-16賽季CBA聯賽之山東
日期:2017-11-10 14:32:142016科比退役紀念章
日期:2017-09-02 15:42:4715-16賽季CBA聯賽之佛山
日期:2017-08-28 17:11:5515-16賽季CBA聯賽之浙江
日期:2017-08-24 16:55:1715-16賽季CBA聯賽之青島
日期:2017-08-17 19:55:2415-16賽季CBA聯賽之天津
日期:2017-06-29 10:34:4315-16賽季CBA聯賽之四川
日期:2017-05-16 16:38:55黑曼巴
日期:2016-07-19 15:03:112015亞冠之薩濟拖拉機
日期:2015-05-22 11:38:5315-16賽季CBA聯賽之北京
日期:2019-08-13 17:30:53
跳轉到指定樓層
1 [收藏(0)] [報告]
發表于 2023-04-22 13:20 |只看該作者 |倒序瀏覽
本帖最后由 523066680 于 2023-04-22 13:24 編輯

環境:Win10, Strawberry Perl

經常遇到需要多線程處理的需求,但是在終端混合輸出的結果非;靵y,即使每條信息加上線程ID,又或是使用不同的縮進。
最初考慮在線程間共享GUI句柄,結果發現僅有的幾個GUI框架并不支持線程共享。
    于是改了方案,單獨開一個線程跑GUI,創建一個線程共享的字符串數組,存儲日志。
    通過 open $H, ">", \$str 的方式為字符串變量創建輸出流句柄,然后 select $H 取代STDOUT輸出。
    在GUI的文本顯示模塊中動態更新字符串內容,目的達成。




  1. # Code By 523066680
  2. use utf8;
  3. use Modern::Perl;
  4. use Encode;
  5. use threads;
  6. use threads::shared;
  7. use Time::HiRes qw/sleep time/;
  8. use IUP ':all';

  9. STDOUT->autoflush(1);
  10. my $th_count = 8;

  11. # 不同線程的日志緩存
  12. my @log :shared;
  13. @log = map { utf8("線程 $_ \n") } ( 0 .. $th_count );  # 0 占位

  14. my @ths;
  15. # 創建線程
  16. grep { push @ths, threads->create( \&th_func, $_ ) } ( 1 .. $th_count );
  17. push @ths, threads->create( \&GUI, 4 );

  18. # 等待運行結束
  19. while ( threads->list(threads::running) ) { sleep 0.2 };

  20. # 線程分離/結束
  21. grep { $_->detach() } threads->list(threads::all);

  22. sub th_func
  23. {
  24.     my ( $id ) = @_;

  25.     $SIG{'KILL'} = sub { threads->exit(); };

  26.     # printf "%d %s\n", $id, $log[$id];
  27.     open my $FH, ">>:utf8", \$log[$id];
  28.     select $FH;

  29.     my $n = 1;
  30.     while ( 1 )
  31.     {
  32.         printf "線程 %d -> %03d\n", $id, $n++;
  33.         sleep 0.2;
  34.     }
  35. }

  36. sub GUI
  37. {
  38.     our @edit;
  39.     for my $n ( 1 .. $th_count )
  40.     {
  41.         push @edit, IUP::Text->new(
  42.             FONT => "Simsun, 10",
  43.             MULTILINE => "YES",
  44.             BORDER    => "YES",
  45.             SCROLLBAR => "VERTICAL",
  46.             EXPAND=>"YES",
  47.             BGCOLOR => "#000000",
  48.             FGCOLOR => "#FFFFFF",
  49.             VALUE => "",
  50.         );
  51.     }

  52.     my $box1 = IUP::Vbox->new(
  53.         TABTITLE => "1~4",
  54.         child => [
  55.             IUP::Hbox->new(
  56.                 child => [ $edit[0], $edit[1] ],
  57.                 GAP    => 5,
  58.                 MARGIN => "5x5"
  59.             ),
  60.             IUP::Hbox->new(
  61.                 child => [ $edit[2], $edit[3] ],
  62.                 GAP    => 5,
  63.                 MARGIN => "5x5"
  64.             ),
  65.         ],
  66.         EXPAND => 1,
  67.         GAP    => 5,
  68.         MARGIN => "5x5"
  69.     );

  70.     my $box2 = IUP::Vbox->new(
  71.         TABTITLE => "5~8",
  72.         child => [
  73.             IUP::Hbox->new(
  74.                 child => [ $edit[4], $edit[5] ],
  75.                 GAP    => 5,
  76.                 MARGIN => "5x5"
  77.             ),
  78.             IUP::Hbox->new(
  79.                 child => [ $edit[6], $edit[7] ],
  80.                 GAP    => 5,
  81.                 MARGIN => "5x5"
  82.             ),
  83.         ],
  84.         EXPAND => 1,
  85.         GAP    => 5,
  86.         MARGIN => "5x5"
  87.     );

  88.     my $tabs = IUP::Tabs->new( child => [$box1, $box2 ], TABTYPE=>"TOP",
  89.         PADDING => "10x10",
  90.         FONTSIZE => "12",
  91.         T**RIENTATION => "HORIZONTAL",
  92.     );

  93.     my $dlg = IUP::Dialog->new(
  94.         child => $tabs,
  95.         TITLE => "Console",
  96.         SIZE  => "450x250",
  97.     );

  98.     IUP::Timer->new(ACTION_CB => msg_update->( \[url=home.php?mod=space&uid=31104]@edit[/url] ), TIME => 200, RUN=>'YES');
  99.     $dlg->ShowXY( IUP_CENTER, IUP_CENTER );

  100.     IUP->MainLoop;

  101.     # 如果GUI線程結束
  102.     for (  threads->list(threads::all) )
  103.     {
  104.         if ( $_->tid() != threads->tid() )
  105.         {
  106.             $_->kill("KILL")->detach();
  107.             printf "detach %d\n", $_->tid();
  108.         }
  109.     }
  110. }

  111. # 日志更新顯示
  112. sub msg_update
  113. {
  114.     my ( $edit ) = @_;
  115.     # 記錄每個ID日志的offset,只打印增量的部分
  116.     # 解決滾動條反彈到頂部的問題 - 如果每次都使用 $obj->VALUE 打印整個日志的話
  117.     my @offset = map {0} ( 0 .. $th_count );

  118.     return sub
  119.     {
  120.         for my $id ( 1 .. $th_count )
  121.         {
  122.             my $len = length( $log[$id] );
  123.             if ( $offset[$id] == 0 )
  124.             {
  125.                 $log[$id] =~ s/\n$//;
  126.                 $edit->[$id-1]->APPEND( $log[$id], 0 );
  127.                 $offset[$id] = $len - 1; # 去掉一個換行符
  128.             }
  129.             elsif ( $len > $offset[$id] )
  130.             {
  131.                 my $str = substr( $log[$id], $offset[$id] );
  132.                 $str=~s/\n$//;
  133.                 $edit->[$id-1]->APPEND( $str );
  134.                 $offset[$id] = $len;
  135.             }

  136.             #$edit->[$id-1]->VALUE( $log[$id] );
  137.         }

  138.         return IUP_DEFAULT;
  139.     };
  140. }

  141. sub gbk { encode('gbk', $_[0]) }
  142. sub utf8 { encode('utf8', $_[0]) }
  143. sub u2gbk { encode('gbk', decode('utf8', $_[0])) }
  144. sub uni { decode('utf8', $_[0]) }
復制代碼



論壇徽章:
12
子鼠
日期:2014-10-11 16:46:482016科比退役紀念章
日期:2018-03-16 10:24:0515-16賽季CBA聯賽之山東
日期:2017-11-10 14:32:142016科比退役紀念章
日期:2017-09-02 15:42:4715-16賽季CBA聯賽之佛山
日期:2017-08-28 17:11:5515-16賽季CBA聯賽之浙江
日期:2017-08-24 16:55:1715-16賽季CBA聯賽之青島
日期:2017-08-17 19:55:2415-16賽季CBA聯賽之天津
日期:2017-06-29 10:34:4315-16賽季CBA聯賽之四川
日期:2017-05-16 16:38:55黑曼巴
日期:2016-07-19 15:03:112015亞冠之薩濟拖拉機
日期:2015-05-22 11:38:5315-16賽季CBA聯賽之北京
日期:2019-08-13 17:30:53
2 [報告]
發表于 2023-04-22 13:21 |只看該作者

[Perl]GUI顯示多線程任務進度

本帖最后由 523066680 于 2023-04-22 13:27 編輯

發重了,清除內容
論壇使用上是有些問題了,時代也變了,少人用論壇

GUI顯示多線程日志輸出.gif (673.04 KB, 下載次數: 19)

GUI顯示多線程日志輸出.gif

論壇徽章:
7
巳蛇
日期:2013-11-28 09:22:59天秤座
日期:2014-10-25 15:40:452015年辭舊歲徽章
日期:2015-03-03 16:54:152015年迎新春徽章
日期:2015-03-04 09:53:172015亞冠之德黑蘭石油
日期:2015-07-15 08:46:452015亞冠之平陽省
日期:2015-11-08 16:27:53白銀圣斗士
日期:2015-11-14 09:58:12
3 [報告]
發表于 2023-05-31 14:37 |只看該作者
用Win32::GUI,再用不同的線程更新不同的標簽(Label)不是更好看?

論壇徽章:
12
子鼠
日期:2014-10-11 16:46:482016科比退役紀念章
日期:2018-03-16 10:24:0515-16賽季CBA聯賽之山東
日期:2017-11-10 14:32:142016科比退役紀念章
日期:2017-09-02 15:42:4715-16賽季CBA聯賽之佛山
日期:2017-08-28 17:11:5515-16賽季CBA聯賽之浙江
日期:2017-08-24 16:55:1715-16賽季CBA聯賽之青島
日期:2017-08-17 19:55:2415-16賽季CBA聯賽之天津
日期:2017-06-29 10:34:4315-16賽季CBA聯賽之四川
日期:2017-05-16 16:38:55黑曼巴
日期:2016-07-19 15:03:112015亞冠之薩濟拖拉機
日期:2015-05-22 11:38:5315-16賽季CBA聯賽之北京
日期:2019-08-13 17:30:53
4 [報告]
發表于 2023-06-06 22:02 |只看該作者
本帖最后由 523066680 于 2023-06-06 22:03 編輯

回復 3# b114213903

你是對的
您需要登錄后才可以回帖 登錄 | 注冊

本版積分規則 發表回復

  

北京盛拓優訊信息技術有限公司. 版權所有 京ICP備16024965號-6 北京市公安局海淀分局網監中心備案編號:11010802020122 niuxiaotong@pcpop.com 17352615567
未成年舉報專區
中國互聯網協會會員  聯系我們:huangweiwei@itpub.net
感謝所有關心和支持過ChinaUnix的朋友們 轉載本站內容請注明原作者名及出處

清除 Cookies - ChinaUnix - Archiver - WAP - TOP
   日韩综合区视频第一页导航,无码JK粉嫩小泬在线观看,午夜精品A片一区二区三区,日日躁夜夜躁狠狠躁麻豆,大胆国模,免费观看无遮挡www的网站