gpt4 book ai didi

iphone - 如何处理setDelegate : when using multipe threads

转载 作者:行者123 更新时间:2023-12-03 17:36:50 26 4
gpt4 key购买 nike

我在使用第三方库时遇到了问题,并且不确定解决该问题的常见模式是什么。

我正在使用 asi-http-request 类,它使用线程异步获取 http 对象。

在我的对象 dealloc() 方法中,我这样做

[request setDelegate:nil];
[request release];

但是,在这种情况发生后,有时仍会调用委托(delegate)。 (我可以看到,当发生这种情况时,请求对象的委托(delegate)字段为零。)如果委托(delegate)已经被销毁,这有时会导致崩溃。

我相信这是一个竞争条件。来自 ASIHTTPRequest 的调用委托(delegate)的代码如下所示:

// Let the delegate know we are done
if ([self didFinishSelector] && [[self delegate] respondsToSelector:[self didFinishSelector]]) {
[[self delegate] performSelectorOnMainThread:[self didFinishSelector] withObject:self waitUntilDone:[NSThread isMainThread]];
}

如果在主线程上发生 setDelegate 调用时已调用(但未完成)performerSelectorOnMainThread,则会出现问题。

一种解决方案是在“didFinishSelector”周围添加一个包装器,在调用选择器之前检查(在主线程上)委托(delegate)是否仍为非零,但这会导致大量包装器。

这里有一些背景:

http://groups.google.com/group/asihttprequest/browse_thread/thread/721220b9645f4a42

对此的“正常”解决方案的所有建议表示赞赏!

谢谢

约瑟夫

最佳答案

我最初的想法(包装“didFinishSelector”,在调用选择器之前检查主线程委托(delegate)是否仍为非零)被证明是正确的解决方案,正如苹果开发论坛上的乐于助人的人所证实的那样:

https://devforums.apple.com/message/255935#255935

为了避免担心最终会出现大量包装器,我设法只创建一个包装器:

- (void)callSelectorCallback:(SEL *)selectorPtr withTarget:(id *)targetPtr
{
id target = *targetPtr;
SEL selector = *selectorPtr;

if (!selector || !target)
return;

if ([target respondsToSelector:selector])
{
[target performSelector:selector withObject:self];
}
}

- (void)callSelector:(SEL *)selector withDelegate:(id *)target
{
if (!*selector || !*target)
return;

SEL callback = @selector(callSelectorCallback:withTarget:);
NSMethodSignature *signature = [ASIHTTPRequest instanceMethodSignatureForSelector:callback];
NSInvocation *invocation = [NSInvocation invocationWithMethodSignature:signature];
[invocation setSelector:callback];
[invocation setTarget:self];
[invocation setArgument:&selector atIndex:2];
[invocation setArgument:&target atIndex:3];

[invocation performSelectorOnMainThread:@selector(invoke) withObject:nil waitUntilDone:[NSThread isMainThread]];
}

然后当我想调用委托(delegate)时,代码看起来像这样:

[self callSelector:&didFinishSelector withDelegate:&delegate];

据我从实验和代码分析中可以看出(并假设 setDelegate 仅从主线程调用),这是 100% 安全的。通过在 callSelectorCallback 中获取对象锁,可以确保非主线程对 setDelegate 的调用是安全的。

关于iphone - 如何处理setDelegate : when using multipe threads,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/3158356/

26 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com