如何在后台线程上进行长时间操作,然后在主线程上更新UI

时间:2013-02-10 02:03:14

标签: objective-c macos cocoa

我必须做一个可能需要很长时间才能完成的IO操作。通过按钮调用IO操作。 当然,UI挂起,直到操作完成。所以我想我需要在某些后台线程上执行IO,但是当操作完成时,我必须更新窗口的标签以指示操作完成。我想我应该在主线程上做什么(比如java中的EDT和C#中的类似),对吗?

在C#中有类似TaskAsync的类,在Java android中类似。这让你可以在另一个线程中完成长任务,当任务完成时,在主线程上调用一个处理程序,以便可以在主线程上更新UI,

cocoa究竟要做什么类似的任务,即允许在单独的线程上进行长操作而不是main,然后以某种方式有助于更新主线程上的用户界面。

2 个答案:

答案 0 :(得分:1)

您的长时间运行操作应移至NSOperation子类

AhmedsOperation.h

@interface AhmedsOperation : NSOperation

@end

AhmedsOperation.m

@implementation AhmedsOperation

// You override - (void)main to do your work
- (void)main
{
    for (int i = 0; i < 1000; i++) {
        if ([self isCancelled]) {
            // Something cancelled the operation
            return;
        }

        sleep(5);

        // Emit a notification on the main thread
        // Without this, the notification will be sent on the secondary thread that we're
        // running this operation on
        [self performSelectorOnMainThread:@(sendNotificationOnMainThread:)
                               withObject:[NSNotification notificationWithName:@"MyNotification"
                                                                        object:self
                                                                      userInfo:nil]
                            waitUntilDone:NO];
    }
}

- (void)sendNotificationOnMainThread:(NSNotification *)note
{
    NSNotificationCenter *nc = [NSNotificationCenter defaultCenter];
    [nc postNotification:note];
}

然后在您的主代码中,当您想要进行操作时,只需创建一个AhmedsOperation对象,然后将其推送到NSOperationQueue并收听通知。

AhmedsOperation *op = [[AhmedsOperation alloc] init];
NSOperationQueue *defaultQueue = [MLNSample defaultOperationQueue];

NSNotificationCenter *nc = [NSNotificationCenter defaultCenter];
[nc addObserver:self
       selector:@selector(progressUpdateNotification:)
           name:@"MyNotification"
         object:op];

[defaultQueue addOperation:op]; 

答案 1 :(得分:0)

假设您有一个想要更新UI的视图控制器的句柄,您可以使用NSObject“performSelectorOnMainThread:withObject:waitUntilDone:”方法。

2)你也可以使用这样的代码来使用Grand Central Dispatch:

dispatch_async(dispatch_get_main_queue(), ^{
    [viewController doSomethingWhenBigOperationIsDone];
}); 

3) 或者您甚至可以从后台线程发布NSNotification,其中观察者(在主线程中)可以更新UI。

You might find some additional useful information in this related question