【问题标题】:Implementing background worker - Obj C/Cocoa实现后台工作者 - Obj C/Cocoa
【发布时间】:2014-02-14 11:12:55
【问题描述】:

我的可可应用中有 2 个窗口。主窗口打开一个子窗口。单击子窗口上的 OK 后,我在主窗体上调用一个 deligate,它将告诉子窗口上单击了 OK 按钮。

现在,我需要“在后台”在主窗口上运行一个长时间运行的进程,这样窗口就不会变得无响应。我也有进度条,应该显示这个长期运行过程的进度。

请告诉我,实现这一目标的最佳方法是什么。

【问题讨论】:

    标签: objective-c macos cocoa


    【解决方案1】:

    您应该从 Apple 的 Concurrency Programming Guide 开始。

    特别是关于 NSOperationQueue 的部分。

    【讨论】:

      【解决方案2】:

      您可以为此使用Grand Central Dispatch。首先,您创建一个调度队列,其中包含您要在另一个线程上执行的操作。每个操作都表示为一个 Objective-C 块(闭包)。

      首先你得到一个队列来把你想运行的任务放在另一个线程上。

      dispatch_queue_t queue = dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0);
      

      然后你在这个队列上放置一个代表你想要做的工作的块:

      dispatch_async(queue, ^{
          // this happens on separate thread
          NSImage *image = produceImageFromSomeReallySlowOperation()
      
          dispatch_async(dispatch_get_main_queue(), ^{
              // this happens on main thread
              [myView setImage:image];
          });
      
      });
      

      dispatch_get_main_queue() 函数返回用于在主线程(执行 GUI)上的操作的队列。这意味着[myView setImage:image] 将在主线程上执行。您可以将进度条的更新放在这里。只需在主队列上调度以更新算法中每个有意义的点的进度。

      所有这些也可以使用NSOperation 来执行,它为相同的功能提供了更高级别的Objective-C 接口。但是直接使用 GCD 有时更容易。这取决于你想做什么。

      【讨论】:

      • Apple 建议您始终使用 API 的最高级别抽象,除非您需要仅由较低级别 API 提供的特定行为。所以你真的应该推荐 NSOperationQueue
      • @Jeff: NSOperationQueue 是一个简洁的类,但 GCD 也同样通用,我认为它也更容易上手。 NSOperationQueue 需要一些练习,有时会根据我的经验为新用户拉头发。
      • @SevenBits 有趣的是你有同样的经历。我也发现 NSOperation 更难推理。尽管 NSOperation 更高级别,但它更旧,所以我认为 GCD 设计得更好是有道理的,因为它是一个更新的 API,具有后见之明的好处。
      • @AdamSmith 否则,这两个 API 都很好用。我个人更多地使用 GCD,所以我不必继承 NSOperation,但两者都可以让你做一些事情,比如你想在哪个线程上运行等等。每个都有优点和缺点。
      猜你喜欢
      • 1970-01-01
      • 2011-10-30
      • 2011-03-17
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2023-03-12
      • 1970-01-01
      相关资源
      最近更新 更多