我有一个应用程序,可以从网络中提取数据,解析数据,并在搜索界面中编译结果。由于数据不相互依赖,因此多线程应用程序同时执行多个获取和分析是有意义的。我在我编写的搜索和解析对象上使用NSInvocationOperation来执行这个函数。
在控制器对象中,我有以下方法:
-(void) searchAndParseAsynchronously {
NSPort *serverPort = [NSMachPort port];
NSConnection *serverConnection = [NSConnection connectionWithReceivePort:serverPort sendPort:serverPort];
[serverConnection setRootObject:self];
for (NSURL *urlToProcess in self.urlsToFetch)
{
BaseSearchParser *searcherForURL = [BaseSearchParser newSearchParserWithParameters:self.searchParams];
searcherForURL.urlToDocument = urlToDocument;
SearchThreader *searchThreader = [SearchThreader new];
searchThreader.threadConnection = comConnection;
searchThreader.targetSchema = searcherForURL;
NSInvocationOperation *threaderOperation = [[NSInvocationOperation alloc] initWithTarget:searchThreader
selector:@selector(executeSearchParse)
object:nil];
[self.operationQueue addOperation:threaderOperation];
}
}应用程序依赖于Core数据,我收集到的这些数据大多是线程不安全的。对于每个搜索/解析操作,我都有一个不同的NSManagedObjectContext (一个用于控制器),并且只在操作或代理对象之间传递NSManagedObjectId。
这些操作通过NSConnection对象将完成的解析结果传递给它们的控制器。控制器使用一个NSConnection对象构造NSMachPort,将自身设置为根对象,并向NSInvocationOperations的每个目标提供相同的NSConnection对象。然后控制器将NSInvocationOperation排在队列中,以便在其自己的NSOperationQueue中执行。
在搜索线程对象中,我有以下方法:
-(void) executeSearchAndParse
{
id parentServer = [threadConnection rootProxy];
[parentServer setProtocolForProxy:@protocol(SearchParseProtocol)];
NSArray *importResults = [targetSchema generatedDataSetIds];
[parentServer schemaFinished:targetSchema];
[parentServer addSearchResults:importResults];
}我相信我已经遵循了苹果的例子,通用的线程间通信给这里。
我不得不说,在大多数情况下,这是非常有效的:来自NSConnection rootProxy的通知按预期的方式发布到主线程中的run循环中,直到控制器对象准备就绪。但是,在我的一些测试用例中,它会导致核心数据停止运行,因为有时消息会在与调用NSInvocationOperation对象的rootProxy对象相同的线程中发送给控制器对象。
我已经在控制器中放置了一个调试器点,当搜索/解析操作完成时,该消息将被发送,并且足够肯定的是,有时(只是有时)执行线程不是主线程。有人知道为什么会发生这种情况吗?或者,是否有一种更简单的方法来构造线程间异步通信?还是我对核心数据的处理方法完全偏离了平衡?
提前感谢!
发布于 2009-12-11 13:33:41
我不认为您的方法有任何问题,并且以前使用过类似的NSConnection。我唯一看到的就是我只是使用NSPort而不是显式地使用NSMachPort。
或者,是否有一种更简单的方法来构造线程间异步通信?
我不认为苹果正在为线程间的通信推广分布式对象。IIRC这个猜测主要是基于我所见过的文档,这些文档确实促进了线程间通信的DOs,但是从那以后已经被删除或编辑了。
我还认为与线程相关的performSelector: NSObject方法更易于使用:
- (void)performSelectorOnMainThread:(SEL)aSelector withObject:(id)arg waitUntilDone:(BOOL)wait
- (void)performSelector:(SEL)aSelector onThread:(NSThread *)thr withObject:(id)arg waitUntilDone:(BOOL)wait(而第二个只能从10.5开始)。
https://stackoverflow.com/questions/1887687
复制相似问题