【问题标题】:Change thread priority ERROR_INVALID_HANDLE更改线程优先级 ERROR_INVALID_HANDLE
【发布时间】:2014-12-03 13:31:57
【问题描述】:

我正在尝试更改脚本中的线程优先级,但没有成功,这是详细信息。

$thr = threads->new(\&someFunction, 
                    $shared variable 1,
                    $shared variable 2, 
                   );

我尝试过使用threads::State

$thr->priority(2);

没有成功

所以,我认为Win32::API 必须工作

my $functionGetLastError= Win32::API->new('Kernel32', 
                                          'GetLastError',
                                          '', 
                                          'N'
                                       );
my $functionSetThreadPriority= Win32::API->new('Kernel32', 
                                               'SetThreadPriority',
                                               'II', # I've tried 'PI' and 'II' as well
                                               'N'
                                              );
my $h = $thr->_handle();
my $success = $functionSetThreadPriority->Call( $h, 2 );
warn "Return Error #".$functionGetLastError->Call() if !$success;

再次,没有成功:(,但现在我有一个线索,脚本返回错误号

最后一个错误 6

来自MSDN site, System Error Codes (0-499),好像报错了

ERROR_INVALID_HANDLE

我做错了什么?

【问题讨论】:

标签: multithreading perl winapi thread-priority


【解决方案1】:

$thread->_handle 奇怪地返回一个HANDLE*,而SetThreadPriority 期望一个HANDLE。您需要取消引用指针,您可以执行以下操作:

use constant THREAD_PRIORITY_HIGHEST => 2;

sub SetThreadPriority {
   my ($thread, $priority) = @_;

   # $thread->_handle() returns a HANDLE*.
   my $handle_ptr    = $thread->_handle();
   my $packed_handle = unpack('P'.HANDLE_SIZE, pack(PTR_FORMAT, $handle_ptr));
   my $handle        = unpack(HANDLE_FORMAT, $packed_handle);

   state $SetThreadPriority = (
      Win32::API->new('Kernel32', 'SetThreadPriority', 'Ni', 'i')
         or die("Loading SetThreadPriority: $^E\n")
   );

   return $SetThreadPriority->Call($handle, $priority);
}

这是完整的测试程序:

use strict;
use warnings;
use feature qw( say state );

use threads;
use threads::shared;

use Carp       qw( croak );
use Config     qw( %Config );
use Win32::API qw( );

sub uint_format {
     $_[0] == 4 ? 'L'
   : $_[0] == 8 ? 'Q'
   : croak("Unsupported")
}

use constant PTR_SIZE   => $Config{ptrsize};
use constant PTR_FORMAT => uint_format(PTR_SIZE);

use constant HANDLE_SIZE   => PTR_SIZE;
use constant HANDLE_FORMAT => PTR_FORMAT;

use constant THREAD_PRIORITY_HIGHEST => 2;

sub SetThreadPriority {
   my ($thread, $priority) = @_;

   # $thread->_handle() returns a HANDLE*.
   my $handle_ptr    = $thread->_handle();
   my $packed_handle = unpack('P'.HANDLE_SIZE, pack(PTR_FORMAT, $handle_ptr));
   my $handle        = unpack(HANDLE_FORMAT, $packed_handle);

   state $SetThreadPriority = (
      Win32::API->new('Kernel32', 'SetThreadPriority', 'Ni', 'i')
         or die("Loading SetThreadPriority: $^E\n")
   );

   return $SetThreadPriority->Call($handle, $priority);
}

{
   my $done :shared = 0;

   my $thread = async {
      { lock($done); cond_wait($done) while !$done; }
   };

   my $rv = SetThreadPriority($thread, THREAD_PRIORITY_HIGHEST);
   say $rv ? "Success" : "Error: $^E";

   { lock($done); $done = 1; cond_broadcast($done); }
   $thread->join();
}

请注意,您可以使用$^E 访问GetLastError

SetThreadPriority($handle, THREAD_PRIORITY_HIGHEST)
   or die("SetThreadPriority: $^E\n";

【讨论】:

  • @user2842165,已更新
  • 我会说这是一个错误,但很可能在现阶段无法再更改。在threads.pm中不是第一个这样的:-/
【解决方案2】:

ERROR_INVALID_HANDLE

这表明 _handle 返回的内容不是 Win32::API 可以理解的。我怀疑“P”想要一个字符串缓冲区而不是整数转换指针。 “I”可能是错误的,因为它在 64 位上的大小错误,我会自己尝试“N”。

另外,对于在 Unix 上遇到此问题的未来读者:试试我的 POSIX::RT::Scheduler 模块。

【讨论】:

  • N Win32::API 将其记录为与指针等效的整数。然而,真正的问题是_handle 返回一个HANDLE*,但SetThreadPriority 期望一个HANDLE
  • 我尝试编译 POSIX::RT::Scheduler,但没有成功:(
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2011-06-25
  • 2010-10-10
  • 2010-10-10
  • 1970-01-01
  • 2011-12-02
  • 1970-01-01
相关资源
最近更新 更多