Multithreading Perl TK Gui冻结
我有一个perl tk应用程序,在其中我创建了许多对象,并用对象中的信息更新perl tk gui显示。我需要在gui的树中添加大量作业(比如30k)。如果我一次性添加所有作业,gui将冻结 下面是代码片段:Multithreading Perl TK Gui冻结,multithreading,perl,user-interface,Multithreading,Perl,User Interface,我有一个perl tk应用程序,在其中我创建了许多对象,并用对象中的信息更新perl tk gui显示。我需要在gui的树中添加大量作业(比如30k)。如果我一次性添加所有作业,gui将冻结 下面是代码片段: sub Importjobs { #================= start creation of objects============================= my JobList $self = shift; my $exportedJobList =
sub Importjobs
{
#================= start creation of objects=============================
my JobList $self = shift;
my $exportedJobList = shift;
# third parameter whether to clear the list
$self->clear () unless shift;
my $noOfProcsToBeAdded = shift || 3000;
my $cellCollection = Tasks::CellCollection::instance ();
my $calcActionsPathHash = $cellCollection->caPathCAHash ();
my $collectionCellNames = $cellCollection->allCellNames ();
my @importedJobs = ();
# if the given job list is empty, add import job list to it
push @{$self->_importJobList()}, @$exportedJobList;
$exportedJobList = [];
# do not import new jobs if the previous jobs are still being created
foreach my $taskGenJob(@{$self->getTaskGenJobObjs()}) {
goto FINISH if TaskGenJobState::CREATE == $taskGenJob->state();
}
# now get each job and add it into the imported jobs till the noOfJobs exceeds $noOfJobsToBeAdded
while(my $jobDescription = shift @{$self->_importJobList()}) {
my $taskInstantiation = $jobDescription->{'taskInstantiation'};
my $caPath = $taskInstantiation->{'calcActionPath'};
my $errMsgPrefix = 'Error importing ' . join ('-', $task, $command, $method, $caPath);
my @calcActionList;
if(defined $caPath) {
my $calcAction = $calcActionsPathHash->{ $caPath };
unless($calcAction) {
my $errMsg = $errMsgPrefix . ": the calcAction is not defined within the current CellCollection : " . $caPath;
$logger4Perl -> error ($errMsg);
next;
}
push @calcActionList, $calcAction;
} else {
my @mList;
if(not defined $method) {
push @mList, @{$task->getMethods(cellCollection => $cellCollection, command => $command)};
$method = join(' ', @mList);
} elsif($method eq $task_desc::default_method) {
@mList = ($task_desc::default_method);
} else {
@mList = sort (grep { $_ } split(/\s+|__/, $method));
}
foreach my $m (@mList) {
push(@calcActionList, @{$cellCollection->findCalcActions($task, $command, $m)});
}
}
foreach my $calcAction(@calcActionList) {
my TaskGenJob $job = TaskGenJob->new ();
$logger4Perl->info ("Adding $caPath");
push (@importedJobs, $job);
my $noOfProcsBeingAdded = $job->calculateNoOfJobExecObjs();
$noOfProcsToBeAdded -= $noOfProcsBeingAdded;
}
last if 1 > $noOfProcsToBeAdded;
}
#================= End creation of objects=============================
#Below function updates the GUI display
$self->addJobs (\@importedJobs);
#================= Mechanism which am using so that GUI will be active after certain time limit=============================
FINISH:
if(@{$self->_importJobList()}) {
$self->parentDlg()->parentWnd()->after(60000,
sub {
$GuiTasksAppl::mainDlg->Disable();
$self->importJobList([], 'noclear', 200);
$GuiTasksAppl::mainDlg->Enable();
});
}
}
目前我的做法是使用$noofprocstobeaded变量添加3000个作业,并保持空闲一段时间,然后在一段时间后重复该过程。在这个空闲过程中,有不同的过程在GUI中处理作业
有人能提出比这更好的方法吗???
期待关于线程、共享内存的想法。首先,如果GUI在30k大更新期间冻结(并且从未解冻),那么您可能已经发现了Tk错误,因为这不应该发生。然而,如果它仅仅在一段时间内没有响应,那么减轻延迟是有意义的
在过去,我使用Tk::repeat()或Tk::after()来驱动UI更新例程。用户界面通常不需要以很高的速度更新,因此每隔几百毫秒可能是一个合理的延迟。决定因素在很大程度上取决于您需要的接口的响应程度。然后在作业导入步骤中:将引用附加到UI更新例程的列表中,然后定期调用$MW->update()。更新例程不一定需要在每次调用期间处理完整列表,但您不希望处理过程落后太多
我还建议使用一些视觉指示器来确定更新是否仍在进行中
如果ImportJobs在计算上很昂贵,那么显然可以执行多进程/多线程技巧来利用系统上的多个处理器。但这将增加一点复杂性和测试工作 在添加作业时,您能否
$mw->更新
或$mw->idletasks
?请参见以下说明: