确保方法只由主线程执行

时间:2009-04-11 17:46:10

标签: objective-c multithreading

我有一个objective-c类,我只想从主线程中调用它。

我可以通过向每个选择器添加类似的东西来实现这一点:

- (void) exampleSelector: (id) param {
    if (![NSThread isMainThread]) {
        [self peformSelectorOnMainThread:@selector(exampleSelector:) withObject:param waitUntilDone:YES];
        return;
    }
    // Do stuff it's not safe to do outside the main thread
}

然而,将此添加到每个选择器似乎有点痛苦。有没有什么方法可以自动拦截对这个类的对象的所有调用,检查它所在的线程,如果它不是主线程,则使用performSelectorOnMainThread?

2 个答案:

答案 0 :(得分:1)

嗯。我不确定是否可以这样做;我想不出办法这样做。我倾向于做的是用代理替换对象。代理将负责在正确的线程中将调用转发给对象。

@interface Forwarder : NSObject
{
    id recipient;
}

- (Forwarder *)initWithRecipient:(id)inRecipient;

@end

@implementation Forwarder

- (Forwarder *)initWithRecipient:(id)inRecipient {
    [inRecipient retain];
    recipient = inRecipient;
    return self;
}

- (void)dealloc {
    [recipient release];
    [super dealloc];
}

- (void)forwardInvocation:(NSInvocation *)anInvocation {
    if ([recipient respondsToSelector: [anInvocation selector]]) {
        if (![NSThread isMainThread]) {
            // Note: only works with methods that take one argument. Should add
            // error handling for other methods
            id argument;
            [invocation getArgument: &argument atIndex: 2];
            [recipient performSelectorOnMainThread: [anInvocation selector] withObject: argument waitUntilDone: YES];
        } else {
            [anInvocation invokeWithTarget:recipient];
        }
    } else {
        [super forwardInvocation:anInvocation];
    }
}

- (NSMethodSignature *)methodSignatureForSelector:(SEL)aSelector {
    if ([recipient respondsToSelector: aSelector])
        return [recipient methodSignatureForSelector: aSelector];
    else
        return [super methodSignatureForSelector: aSelector];
}

@end

答案 1 :(得分:0)

也许您应该对方法的调用者施加限制,不要从任意线程调用它。如果主线程被阻塞等待来自线程B的结果,并且线程B调用类似于示例中的方法,则会出现死锁。

相关问题