我需要在 Cocoa 中实现,这是一种依赖多线程的设计。
我从 CoreFoundation 级别开始 - 我创建了一个 CFMessagePort 并将其附加到 CFRunLoop,但这非常不方便,因为(与其他平台不同)它需要有一个(系统范围内的)唯一名称, 并且 CFMessagePortSendRequest 在等待时不处理返回当前线程的回调。可以创建我自己的 CFRunLoopSource 对象,但构建我自己的线程安全队列似乎有些矫枉过正。
然后我从使用 POSIX 线程切换到 NSThreads,调用 performSelector:onThread: 将消息发送到其他线程。这比 CFMessagePort 机制更容易使用,但同样,performSelector:onThread: 不允许主线程将消息发送回当前线程 - 并且没有返回值。
我所需要的只是一个简单的进程中机制(因此我希望不需要发明方案来创建“唯一”名称),它允许我从线程 A 向线程 B 发送消息(并等待回复) ,并且在等待消息时,允许线程 B 向线程 A 发送消息(并等待回复)。
很简单:A 调用 B 重入调用 A 这种情况在单线程上很常见,但是当消息在线程之间时就是死锁 hell 。
最佳答案
使用-performSelectorOnThread:withObject:waitUntilDone: .您传递的对象将是具有属性或其他“插槽”的对象,您可以将返回值放入其中。例如
SomeObject* retObject = [[SomeObject alloc] init];
[anotherObject performSelectorOnThread: whateverThread withObject: retObject waitUntilDone: YES];
id retValue = [retObject retValue];
如果你想要真正复杂,而不是传递你定义的类的对象,使用 NSInvocation对象并简单地 invoke它在另一个线程上(确保不要同时在两个线程上调用相同的 NSInvocation)例如
[invocation performSelectorOnMainThread:@selector(invoke) withObject:NULL waitUntilDone:YES];
编辑
如果你不想等待另一个线程上的处理完成而你想要一个返回值,你就无法避免另一个线程回调到你的线程中。您仍然可以使用调用,例如
[comObject setInvocation: myInvocation];
[comObject setCallingThread: [NSThread currentThread]];
[someObject performSelectorOnMainThread: @selector(runInvocation:) withObject: comObject waitUntilDone: NO];
// in someObject's implementation
-(void) runInvocation: (ComObject*) comObject
{
[[comObject invocation] invoke];
[self perfomSelector: @selctor(invocationComplete:)
onThread: [comObject callingThread]
withObject: [comObject invocation]];
}
如果您不想创建一个新类来传递线程和调用,请改用 NSDictionary,例如
comObject = [NSDictionary dictionaryWithObjectsAndKeys: invocation, "@invocation" [NSThread currentThread], @"thread", nil];
注意对象所有权。各种 performSelector... 方法会同时保留接收器和对象,直到它们完成为止,但是对于异步调用,如果您不小心,它们可能会在一个小窗口中消失。
关于c++ - 向线程发送消息?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/3966406/