【问题标题】:Synchronous Distributed Objects Over NSConnection IssueNSConnection 问题上的同步分布式对象
【发布时间】:2009-12-11 12:14:09
【问题描述】:

我有一个应用程序,它从网络中提取数据、解析它们,然后在搜索界面中编译结果。由于数据不是相互依赖的,因此多线程应用程序以同时执行多个获取和解析是有意义的。我在为执行此功能而编写的搜索和解析对象上使用 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 Data,我收集到的这些数据大多是线程不安全的。我为每个搜索/解析操作(和一个控制器)有一个不同的 NSManagedObjectContext,并且只在操作或代理对象之间传递 NSManagedObjectId。

这些操作通过一个 NSConnection 对象将完成的解析结果传送回它们的控制器。控制器使用 NSMachPort 对象构造 NSConnection,将自己设置为根对象,并将相同的 NSConnection 对象提供给 NSInvocationOperations 的每个目标。然后控制器将 NSInvocationOperation 排入队列以在其自己的 NSOperationQueue 中执行。

在搜索线程对象中我有以下方法:

-(void) executeSearchAndParse
{ 
 id parentServer = [threadConnection rootProxy];
 [parentServer setProtocolForProxy:@protocol(SearchParseProtocol)];

 NSArray *importResults = [targetSchema generatedDataSetIds];

 [parentServer schemaFinished:targetSchema];
 [parentServer addSearchResults:importResults];
}

我相信我已经遵循了 Apple 给出的通用线程间通信示例here

我不得不说,在大多数情况下,这很有效:来自 NSConnection rootProxy 的通知按预期发布到主线程中的运行循环,并等待获取,直到控制器对象准备好。然而,在我的一些测试用例中,它会导致 Core Data 停止工作,因为有时消息会在与调用 rootProxy 对象的 NSInvocationOperation 对象相同的线程中发送到控制器对象。

我在控制器中放置了一个调试器点,当搜索/解析操作完成时发送的消息上,果然,有时(只是有时)执行线程是不是主要的。有谁知道为什么会发生这种情况?或者,有没有更简单的方法来构建线程间异步通信?或者我的 Core Data 方法是否完全不合时宜?

提前致谢!

【问题讨论】:

    标签: objective-c cocoa multithreading core-data distributed-objects


    【解决方案1】:

    我认为您的方法没有任何问题,并且之前以类似的方式使用过NSConnection。我唯一看到的是我只是使用了NSPort,而不是明确使用NSMachPort

    或者,有没有更简单的方式来构造线程间异步通信?

    我认为 Apple 不再推广分布式对象以进行线程间通信。 IIRC 这个猜测主要基于我看到的文档,这些文档确实促进了线程间通信的 DO,但此后已被删除或编辑。

    我也觉得线程相关的 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 开始可用)。

    【讨论】:

    • 感谢您的回复。我之前在文档中看到过performSelectorOnMainThread 消息,但由于其被认为是低级的性质而回避了它。今天晚些时候我会试一试。此外,(如果它工作的话)它大大简化了框架的设计。这些端口和连接会很快变得混乱!再次感谢!
    猜你喜欢
    • 1970-01-01
    • 2012-05-24
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2011-06-30
    • 2011-09-04
    相关资源
    最近更新 更多