2

这本质上就是我正在做的同步运行异步方法的操作:

这在调用一次时基本上可以工作,但是当多次调用时,它最终会停留在 while 循环中并且永远不会收到信号。关于如何将计时器设置为最终超时的任何想法?

__block SomeClass *result = nil;

dispatch_semaphore_t semaphore = dispatch_semaphore_create(0);
dispatch_queue_t queue = dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_LOW, 0UL);
dispatch_async(queue, ^{
    [[SomeManager sharedInstance] someMethodWithCallback:^(id responseObject, NSError *error) {
        if (!error) {
            result = (SomeClass *)ResponseObject;
        }

        dispatch_semaphore_signal(semaphore);
    }];
});

// wait with a time limit
while (dispatch_semaphore_wait(semaphore, DISPATCH_TIME_NOW)) {
    [[NSRunLoop currentRunLoop] runMode:NSDefaultRunLoopMode beforeDate:[NSDate dateWithTimeIntervalSinceNow:0]];
}

dispatch_release(semaphore);

谢谢

4

3 回答 3

1

在我看来,这有点像 GCD 滥用。;) 您是否正在运行运行循环,因为这是在主线程上执行的?为什么不直接使用完成处理程序中的 dispatch_async() 来调用主线程上的处理程序?例如:

- (void)handleDataReady: (id) results error: (NSError *) error {
    // update your app
}

- (void)performAsyncUpdate {
    dispatch_queue_t queue = dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_LOW, 0UL);
    dispatch_async(queue, ^{
        [[SomeManager sharedInstance] someMethodWithCallback:^(id responseObject, NSError *error) {
            dispatch_async(dispatch_get_main_queue(), ^{
                [self handleDataReady:responseObject error:error];
        }];
    });
}
于 2013-07-19T17:26:29.067 回答
1

如果你真的想让它同步,即阻塞调用线程直到操作完成然后使用下面的模式(当然你想尽可能避免阻塞线程)

NSCondition *waitCondtion = [NSCondition new];
__block BOOL completed = NO;

dispatch_queue_t queue = dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_LOW, 0UL);
dispatch_async(queue, ^{
    [[SomeManager sharedInstance] someMethodWithCallback:^(id responseObject, NSError     *error) {
        if (!error) {
            result = (SomeClass *)ResponseObject;
        }

       [waitCondtion lock];
       completed = YES;
       [waitCondition signal];
       [waitCondition unlock];
    }];
});

[waitCondtion lock];
if (!completed)
    [waitCondtion wait];
[waitCondition unlock];

您还可以使用“waitUntilDate:”在一段时间后使等待超时。

但是,此模式仅在“someMethodWithCallback 不在被阻塞的同一线程上调用其回调块”时才有效。我复制了您的代码,因为“someMethodWithCallback”是如何实现的并不明显。由于此方法使用异步模式,那么它必须异步执行某些操作,因此为什么要在 dispatch_async 中调用它?它将在哪个线程上调用其回调块?

于 2013-09-30T09:14:43.170 回答
0

您应该使用完成处理程序完成时处理结果所需的任何代码“填充”完成处理 程序(并且还完全删除该运行循环)。

为了“中止”异步操作,您应该提供一条cancel消息,将其发送给异步结果提供程序。

在您的情况下,由于您有一个单身人士,因此cancel必须像这样发送消息:

 [[SomeManager sharedInstance] cancel];

当操作收到cancel消息时,它应该尽快中止其任务并使用适当的NSError对象调用完成处理程序,指示它已被取消。

请注意,取消消息可能是异步的——这意味着,当它返回时,接收者仍可能执行任务。

您可以通过设置计时器来实现“超时”,该计时器向操作发送取消消息,除非在操作完成时它已失效。

于 2013-07-19T17:46:02.890 回答