Objective-C中线程和流的问题



我真的不知道这是线程的问题,但我不知道还有什么可能导致我的问题。我有一个iOS应用它有一个NSStreamDelegate调用

- (void) stream:(NSStream *)stream handleEvent:(NSStreamEvent)eventCode

委派被赋予一个AppDelegate的句柄,并且在StreamDelegate的其他部分,AppDelegate存在。然而,在stream:handleEvent:中,当我试图将结果传递回AppDelegate进行额外处理时,我得到了EXC_BAD_ACCESS错误。

我认为这可能是线程问题的唯一原因是stream:handleEvent: states:

只有当流被安排在运行循环中时,委托才会收到此消息。消息在流对象的线程上发送。委托应该检查streamEvent以确定它应该采取的适当操作。

是否"流对象的线程"指的是我的StreamDelegate?或者这是对传递给方法的流的引用?我假设是后者,但我想确保我没有搞错。

如果它一个不同的线程比我的AppDelegate坐,然后是什么导致我的问题?如果是,我该如何处理?

编辑: per @bbum,我正在更新以指示我所做的。

在四处摸索之后,我尝试了一些我考虑过但后来放弃的东西。基本上,我创建了一个虚拟类,它被实例化并从stream:handleEvent:调用。我用

来调用完成工作的方法
[man performSelectorOnMainThread:@selector(saveEvent:) withObject:jsonDict waitUntilDone:YES];

在saveEvent:内部,我回调AppDelegate,(几乎!)一切都从那一点开始工作。

我目前有一个问题,调试器抱怨试图写入一个不存在的文件。我还不知道为什么会这样。文件名看起来很可疑,就像在"iPhone Simulator/5.0/Applications/"下为应用程序创建的散列目录,但我还没有弄清楚在哪里,确切地说,错误正在发生。

真正混乱的部分是,我根本无法获得任何崩溃的堆栈跟踪。我尝试过使用LLVM 3.0和LLVM GCC 4.2,以及相应的调试器,但没有。我使用Xcode 4.2。我在4.1版本中没有这个问题。

谢谢你的智慧之言,@bbum。感谢。一旦我完全解决了这个问题,我会发布另一个更新。

编辑(2011-10-18):(更新:不要紧;我是个白痴。我正在将流读入字节数组,但没有声明显式的大小。我遇到了缓冲区溢出的问题。现在都可以用了。

由于上面的错误,我已经绞尽脑汁好几天了,然后重写了代码。我几乎又能让一切正常工作了,但是线程似乎仍然在咬我的屁股。

我得到以下错误:

警告:无法恢复先前选择的帧。

我正在做的是在NSInputStream上接收数据,并将其写出来,然后尝试刷新视图,以指示更新。在调用之后的某个时刻,我应该看到对viewWillAppear:(BOOL)animated的调用,但是上面的警告首先出现,并且应用程序锁定。

我在上面搜索了很多,通常错误是在有某种无限循环,或者堆栈溢出,或者内存被破坏的时候出现的。我不认为会发生这种事。我仍然认为我遇到了一个问题,我的线程交叉了,堆栈变得混乱了。我就是不明白为什么。

上面调用的saveEvent: selector完成它的工作,然后修改视图中的属性以表明它是脏的。这个属性被触动了。当我打断它的时候,我看到它发生了。但是viewWillAppear:永远不会被调用。

这真是太令人沮丧了。这似乎是一件很简单的事情,但这是多么混乱啊。

是否"流对象的线程"指的是我的StreamDelegate?或者是对流的引用被传递到方法中?我假设我想确认一下我没有弄错。

每个线程只能有一个运行循环。该委托将在拥有流被调度的运行循环的任何线程上被调用。

如果它和AppDelegate所在的线程不同,则是是什么导致了我的问题?如果是,我该如何处理?

可能是;如果你的AppDelegate不是线程安全的,并且流被安排在一个非主线程上,那么很可能出现问题。

没有更多的信息,不可能说更多。由于应用程序正在崩溃,你应该发布回溯,至少。

解决了吗?我正在做一些非常类似的事情,并有它的工作,虽然我遇到了一个问题,随机不接收应该出现在流上的所有字符。

如果有帮助的话,我可以张贴在我的情况下工作的代码。

实际上,我的代码是启动一个后台线程,然后委托使用它来监视流。

-(void)backgroundThreadFunction:(NSObject*)obj
{
    [self setBackgroundThread:[NSThread currentThread]];
    [streamDelegate OpenSession:accessoryInfo];
    while(_continueRunning) {
        NSAutoReleasePool *_pool = [[NSAutoReleasePool alloc] init];
        [[NSRunLoop currentRunLoop] runUntilDate:[NSDate date]];
        [_pool release];
    }
    [self setBackgroundThread:nil];
}

流委托OpenSession指定以以下方式在当前线程上运行。

[[currentSession inputStream] scheduleInRunLoop:[NSRunLoop currentRunLoop] forMode:NSDefaultRunLoopMode];
[[currenSession outputStream] scheduleInRunLoop:[NSRunLoop currentRunLoop] forMode:NSDefaultRunLoopMode];

当我想让appDelegate知道一些事情时,我通常使用一个NSNotification,它已经为事件注册了。

[[NSNotificationCenter defaultCenter] postNotificationName:@"DataReceived" object:_receivedData];

希望对你有帮助。

相关内容

  • 没有找到相关文章

最新更新