我应该为我的UI操作使用后台线程吗?

时间:2010-09-24 12:30:00

标签: multithreading cocoa performance core-data nsoutlineview

背景

  • 我有一个显示TrainingGroup实体的NSOutlineView

  • 每个TrainingGroup代表本地计算机上的文件夹。

  • NSOutlineView绑定到NSTreeController,其获取谓词为IsTrained == 0

  • 每个TrainingGroup都可以分配给一个项目。

  • 每个TrainingGroup都有许多TrainingEntries,显示该文件的工作时间。

  • 将TrainingGroup分配给项目时,IsTrained设置为YES

  • 在分配给项目时,所有后代也分配给该项目,其IsTrained属性也设置为YES

  • 项目列绑定到projectTopLevel属性。

示例

整棵树看起来像这样:

Name                       Project              IsTrained
Users                      nil                  NO
  John                     nil                  NO              
    Documents              nil                  NO
      Acme Project         Acme Project         YES
        Proposal.doc       Acme Project         YES
          12:32-12:33      Acme Project         YES
          13:11-13:33      Acme Project         YES
          ... etc
        Budget.xls         Acme Project         YES
      Big Co Project       Big Co Project       YES
        Deadlines.txt      Big Co Project       YES
        Spec.doc           Big Co Project       YES
      New Project          nil                  NO
        StartingUp.doc     nil                  NO
      Personal Stuff       Personal             YES
        MyTreehouse.doc    Personal             YES
    Movies                 nil                  NO
      Aliens.mov           nil                  NO
      StepMom.mov          nil                  NO

NSOutlineView只能看到这个:

Users                      nil                  NO
  John                     nil                  NO              
    Documents              nil                  NO
      New Project          nil                  NO
        StartingUp.doc     nil                  NO
    Movies                 nil                  NO
      Aliens.mov           nil                  NO
      StepMom.mov          nil                  NO

如果您将电影指定为个人,则视图现在将如下所示:

Users                      nil                  NO
  John                     nil                  NO              
    Documents              nil                  NO
      New Project          nil                  NO
        StartingUp.doc     nil                  NO

代码

TrainingGroup.m

-(void)setProjectTopLevel:(JGProject *)projectToAssign {
    [self setProjectForSelf:projectToAssign];
    [self setProjectForChildren:projectToAssign];
}

-(void)setProjectForSelf:(JGProject *)projectToAssign {
    [self setProject:projectToAssign];
}

-(void)setProjectForChildren:(JGProject *)projectToAssign {
    for (TrainingGroup *thisTrainingGroup in [self descendants]) {
        [thisTrainingGroup setProject:projectToAssign];
        if(projectToAssign != nil) {
            [thisTrainingGroup setIsTrainedValue:YES];
        } else {
            [thisTrainingGroup setIsTrainedValue:NO];
        }
        // Other code updating rules.
    }
}

-(JGProject *)projectTopLevel {
    return [self project];
}

-(NSSet *)untrainedChildren {
    // Code that loops through all children returning those
    // whose isTrained is NO. Omitted for brevity.
}

问题

如上所示,我正在主线程上运行所有项目分配代码。

如果每个文件夹下有数百个时间条目,我的应用就会无法响应。

可能的解决方案

1模态进度条

方法

  • 在不同的上下文中在后台线程上运行项目分配。
  • 完成后,使用标准Core Data合并到主要上下文中。
  • 模式表会阻止任何进一步的活动,直到项目分配完成。

  • 用户可以立即获得有关正在发生的事情的反馈。
  • 该应用仍保持响应。

糟糕

  • 在当前作业完成之前,用户无法执行任何操作。

2非模态微调器

方法

  • 在不同的上下文中在后台线程上运行项目分配。
  • 完成后,使用标准Core Data合并到主要上下文中。
  • 在训练组旁边显示进度微调器,表示它正忙。
  • 完成分配后,培训组将从视图中消失。

  • 用户可以在处理上一个操作时执行其他操作
  • 该应用仍保持响应。均田。见下文。

糟糕

  • 在测试中,当背景上下文合并到主上下文中时,我看到冻结最多3秒。
  • 视图可以在用户执行其他操作的过程中更新,这可能很烦人。
  • 撤消很难实现。

3隐藏

方法

  • 以上,除了在分配时删除了培训组,并且在分配完成之前将其设置为“进行中”。

好与坏

  • 与上述相同,但培训组的排序仍然可以预测。
  • 合并回到主要环境仍有大量冻结。

4提高效果

方法

  • 保持代码不变,在主线程上运行。
  • 提高性能,即使有数千个条目,视图也会冻结最多半秒

  • 应用程序保持响应。
  • 撤消仍然很容易。
  • 架构仍然很简单。

糟糕

  • 根据我的理解,针对Apple的建议 - 不应在主线程上进行密集处理
  • 我可以获得足够好的表现吗?未知的。

我的问题

据我所见,上述选项都不理想。

1。哪个是最佳选择?

2。还有其他选择吗?

第3。我可以改进哪些方法?

1 个答案:

答案 0 :(得分:1)

  1. 我会在后台线程(第2号)上更新
  2. 您可以随时禁用窗口部分的用户输入,并显示加载消息。
  3. 简单易懂 - 仔细检查所有代码,确保所需的呼叫次数最少,并且不要调用任何不必要的功能。您还可以在单​​独的线程上运行一些持久的操作,然后在操作完成时得到通知,这样您就可以在操作继续时处理其他事情。