代码之家  ›  专栏  ›  技术社区  ›  Chris Becke

向线程发送消息?

  •  3
  • Chris Becke  · 技术社区  · 14 年前

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

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

    我只需要一个简单的进程内机制(所以我希望不需要发明创建“唯一”名称的方案),它允许我从线程a向线程B发送消息(并等待答复),并且在等待消息的同时,允许线程B向线程a发送消息(并等待答复)。

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

    2 回复  |  直到 14 年前
        1
  •  2
  •   JeremyP    14 年前

    使用 -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];
    

        2
  •  1
  •   Aidan Steele    14 年前

    你查过了吗 Distributed Objects ?

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

    您还可以选择通过其他关键字指定行为,如 oneway in , out , inout , bycopy byref . 一个 article

    尽管如此,通常的注意事项是:你确定你需要一个线程设计等?还有其他选择,比如 NSOperation (文件 here NSOperationQueue ,它允许您显式地声明依赖项并让magic为您解决它们。或许好好读一读苹果的 Concurrency Programming Guide 去掌握你的选择(不是双关语)。