【发布时间】:2014-02-14 11:12:55
【问题描述】:
我的可可应用中有 2 个窗口。主窗口打开一个子窗口。单击子窗口上的 OK 后,我在主窗体上调用一个 deligate,它将告诉子窗口上单击了 OK 按钮。
现在,我需要“在后台”在主窗口上运行一个长时间运行的进程,这样窗口就不会变得无响应。我也有进度条,应该显示这个长期运行过程的进度。
请告诉我,实现这一目标的最佳方法是什么。
【问题讨论】:
标签: objective-c macos cocoa
我的可可应用中有 2 个窗口。主窗口打开一个子窗口。单击子窗口上的 OK 后,我在主窗体上调用一个 deligate,它将告诉子窗口上单击了 OK 按钮。
现在,我需要“在后台”在主窗口上运行一个长时间运行的进程,这样窗口就不会变得无响应。我也有进度条,应该显示这个长期运行过程的进度。
请告诉我,实现这一目标的最佳方法是什么。
【问题讨论】:
标签: objective-c macos cocoa
您应该从 Apple 的 Concurrency Programming Guide 开始。
特别是关于 NSOperationQueue 的部分。
【讨论】:
您可以为此使用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 有时更容易。这取决于你想做什么。
【讨论】:
NSOperationQueue 是一个简洁的类,但 GCD 也同样通用,我认为它也更容易上手。 NSOperationQueue 需要一些练习,有时会根据我的经验为新用户拉头发。
NSOperation,但两者都可以让你做一些事情,比如你想在哪个线程上运行等等。每个都有优点和缺点。