如何等待异步方法结束? [英] How to wait for an asynchronous method to be over?

查看:364
本文介绍了如何等待异步方法结束?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我有一个需要使用的工具包(与远程服务接口).该工具包查询远程服务并询问结果.它异步执行此操作,在大多数情况下,这是 good ,但不是用于创建简洁的方法.我想使方法类似于以下内容:

I have a toolkit that I need to work with (to interface with a remote service). This toolkit queries the remote service and asks for results. It does this asynchronously, which in most cases is good, but not for creating concise methods. I want to make methods similar to the following:

-(NSArray *)getAllAccounts {
    NSString *query = @"SELECT name FROM Account";
    //Sets "result" to the query response if no errors.
    //queryResult:error:context: is called when the data is received
    [myToolkit query:query target:self selector:@selector(queryResult:error:context:) context:nil];

    //Wait?

    return result.records;
}

问题是,在工具包中,方法使用@selector彼此调用,而不是直接调用,因此获取返回值很困难.此外,实际查询使用:

The problem is, inside the toolkit the methods call each other using @selector, not direct calls, so getting return values is difficult. Further, the actual query uses:

NSURLConnection *connection = [[[NSURLConnection alloc] initWithRequest:aRequest delegate:self] autorelease];

这是异步的.到从服务接收数据时,很早以前我的方法就返回了……没有任何信息.所以我的问题是:有没有办法在数据返回之前暂停执行?我能否在主线程静止时使用第二个线程来获取数据(或使用3个​​线程使主线程不静止?)

Which is asynchronous. By the time the data has been received from the service, my method has long ago returned... without the information. So my question is this: Is there a way to pause execution until the data has been returned? Could I accomplish this using a second thread to get the data while the main thread rests (or using 3 threads so the main thread doesn't rest?)

我不想编辑工具包以将其方法更改(或添加新方法)以使其同步,所以有没有办法按我的意愿制作方法?

I don't want to edit the toolkit to change their method (or add a new one) to be synchronous, so is there a way to make a method as I want?

推荐答案

您可能要考虑不使其全部同步,尤其是如果帖子中的示例代码在主应用程序线程上运行时.如果这样做,则主线程将阻止UI,并且应用程序将停止响应,直到完成远程事务为止.

You might want to consider NOT making it all synchronous, especially if the sample code in your post is run on your main application thread. If you do that, the main thread will block the UI and the application will cease to respond until the remote transaction is complete.

因此,如果您真的坚持使用同步方法,那么绝对应该在后台线程中执行此操作,以使UI不会变得无响应,这实际上可能导致您的App被iphone上的OS杀死.

Therefore, if you really insist on the synchronous approach, then you should definitely do it in a background thread so that the UI does not become unresponsive, which can actually lead to your App getting killed by the OS on iphone.

要在后台线程中进行工作,我强烈建议您使用Grand Central Dispatch东西,即NSBlockOperation.它将使您不必实际创建和管理线程,并使您的代码更简洁.

To do the work in a background thread, I would strongly recommend using the Grand Central Dispatch stuff, namely NSBlockOperation. It will free you from having to actually create and manage threads and makes your code pretty neat.

要执行同步操作,请查看NSCondition类文档.您可以执行以下操作:

To do the synchronous thing, take a look at the NSCondition class documentation. You could do something like the following:

NSCondition* condition = ...;
bool finished = NO;

-(NSArray *)getAllAccounts {
    [condition lock];
    NSString *query = @"SELECT name FROM Account";
    //Sets "result" to the query response if no errors.
    //queryResult:error:context: is called when the data is received
    [myToolkit query:query target:self selector:@selector(queryResult:error:context:) context:nil];

    while (!finished)
        [condition wait]; 

    [condition unlock];
    return result.records;
}

然后在工具箱调用的方法中提供您要执行的结果:

Then in the method called by the toolkit to provide the results you'd do:

- (void) queryResult:error:context: {
    //  Deal with results
    [condition lock]
    finished = YES;
    [condition signal];
    [condition unlock];
}

您可能希望在类声明中封装条件"和完成"变量.

You'd probably want to encapsulate the "condition" and "finished" variables in your class declaration.

希望这会有所帮助.

更新:这是一些将工作卸载到后台线程的代码:

UPDATE: Here is some code to offload the work to a background thread:

NSOperationQueue* queue = [NSOperationQueue new];
[queue addOperationWithBlock:^{
    //  Invoke getAllAccounts method
}];

当然,您可以保留队列以备后用,并将工作的实际排队移到方法调用中以使事情变得更整洁.

Of course, you can keep the queue around for later use and move the actual queuing of the work to inside your method call to make things neater.

这篇关于如何等待异步方法结束?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆