将消息发送到线程?

时间:2010-10-19 08:15:56

标签: c++ objective-c multithreading cocoa core-foundation

我需要使用cocoa,这是一种依赖于多线程的设计。

我从CoreFoundation级别开始 - 我创建了一个CFMessagePort并将其附加到CFRunLoop,但它非常不方便,因为(与其他平台不同)它需要拥有(系统范围内)唯一名称和CFMessagePortSendRequest在等待时不会将回调处理回当前线程。它可以创建我自己的CFRunLoopSource对象,但构建我自己的线程安全队列似乎有点矫枉过正。

然后我从使用POSIX线程切换到NSThreads,调用performSelector:onThread:将消息发送到其他线程。这比CFMessagePort机制更容易使用,但同样,performSelector:onThread:不允许主线程将消息发送回当前线程 - 并且没有返回值。

我所需要的只是一个简单的进程机制(所以我希望不需要创建方案来创建'唯一'名称),这让我可以从线程A向线程B发送消息(并等待回复) ,并且,在等待消息时,允许线程B向/从线程A发送消息(并等待回复)。

一个简单的:A调用B重新调用一个在单个线程上常见的情况,但是当消息在线程之间时,它就是死锁地狱。

2 个答案:

答案 0 :(得分:2)

使用-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 ...方法保留了接收器和对象,直到它们完成为止,但是如果你不小心,可能会有一个小窗口可能会消失。

答案 1 :(得分:1)

你有没有看过Distributed Objects

它们通常用于进程间通信,但没有真正的原因它不能被限制为具有多个线程的单个进程。更好的是,如果沿着这条路走下去,你的设计将很容易扩展到多个流程甚至多台机器。

您还可以选择通过其他关键字指定行为,例如onewayinoutinoutbycopy和{{ 1}}。由David Chisnall(GNUstep成名)撰写的article解释了这些的基本原理。

所有这一切,通常的警告适用:您确定需要螺纹设计等等吗?还有其他选择,例如使用byref(doc here)和NSOperation,它们允许您明确说明依赖关系并让魔法为您解决它们。也许对Apple的Concurrency Programming Guide有一个很好的解读,以便在您的选项上获得处理(没有双关语)。

我只是在你提到尝试传统的POSIX线程时提出这个建议,这让我相信你可能会尝试应用从其他操作系统收集的知识,而不是充分利用OS X所提供的功能。