如何优化 NSOperationQueue 启动线程的回调

发布于 2024-08-18 07:16:02 字数 2016 浏览 2 评论 0原文

考虑一下:

@interface SomeViewController : UIViewController {
    SomeChildObject *child;
}
@end

@implementation SomeViewController

- (void) viewDidLoad {
    ...
    child.delegate = self;
}

- (void) somethingHappened {
    NSInvocationOperation *operation = [[NSInvocationOperation alloc]
        initWithTarget:child
        selector:@selector(doSomething)
        object:nil];
[someNsOperationQueue addOperation:operation];
[operation release];
}

- (void) callbackA:(SomeData *)someData {
[self performSelectorOnMainThread:@selector(callbackAonMainThread:)
                       withObject:someData
                    waitUntilDone:NO];
}

- (void) callbackAonMainThread:(SomeData *)someData {
    ... do something with results in main thread, e.g UI feedback
}

- (void) callbackB:(SomeData *)someData {
[self performSelectorOnMainThread:@selector(callbackBonMainThread:)
                       withObject:someData
                    waitUntilDone:NO];
}

- (void) callbackBonMainThread:(SomeData *)someData {
    ... do something with results in main thread, e.g UI feedback
}


@end

用英语:

我有一个在主线程中运行的视图控制器,其中有一个子模型对象来执行某些操作(通过网络获取数据)。视图控制器是子级的委托,因此子级可以通过委托发回结果信号。为了执行昂贵的工作,我使用 NSInvocableOperation 生成 child.doSomething 方法,该方法在后台线程中启动该操作。完成后,子进程调用委托(视图控制器)的回调 A 或回调 B 并返回一些结果。由于(我认为)这些回调是在运行 doSomething 调用的同一后台线程中调用的,因此我需要调用 PerformSelectorOnMainThread 将控制权转移回主线程。

这工作正常,但我不喜欢每个回调都有两个与回调相关的方法。 (实际上有更多的回调,所以真正的代码更加臃肿。)理想情况下,我会做这样的事情:

- (void) callbackA:(SomeData *)someData {
    if (not_running_on_main_thread) {
    [self performSelectorOnMainThread:@selector(callbackA:)
                       withObject:someData
                    waitUntilDone:NO];
    } else {
        // now running on main thread, work with the results.
    }
}

问题:

1)如何进行“not_running_on_main_thread”测试?

2)还有其他方法可以减少回调的膨胀吗?

编辑:好的,我在发布之前从未阅读过 NSThread 文档:) 看起来 [NSThread isMainThread] 就是我正在寻找的。但还有其他方法可以重组或使其变得更好吗?

Consider this:

@interface SomeViewController : UIViewController {
    SomeChildObject *child;
}
@end

@implementation SomeViewController

- (void) viewDidLoad {
    ...
    child.delegate = self;
}

- (void) somethingHappened {
    NSInvocationOperation *operation = [[NSInvocationOperation alloc]
        initWithTarget:child
        selector:@selector(doSomething)
        object:nil];
[someNsOperationQueue addOperation:operation];
[operation release];
}

- (void) callbackA:(SomeData *)someData {
[self performSelectorOnMainThread:@selector(callbackAonMainThread:)
                       withObject:someData
                    waitUntilDone:NO];
}

- (void) callbackAonMainThread:(SomeData *)someData {
    ... do something with results in main thread, e.g UI feedback
}

- (void) callbackB:(SomeData *)someData {
[self performSelectorOnMainThread:@selector(callbackBonMainThread:)
                       withObject:someData
                    waitUntilDone:NO];
}

- (void) callbackBonMainThread:(SomeData *)someData {
    ... do something with results in main thread, e.g UI feedback
}


@end

In English:

I have a view controller running in the main thread with a child model object to do something (fetch data over network). The view controller is the delegate for the child, so the child can signal the results back with delegation. To perform the expensive work, I spawn the child.doSomething method with a NSInvocationOperation that launches the operation in a background thread. When done, the child calls the delegate's (view controller's) callbackA or callbackB with some results. Since (I think) these callbacks are invoked in the same background thread where the doSomething call was run, I need to call performSelectorOnMainThread to transfer control back to main thread.

This works fine, but I do not like having two callback-related methods for each callback. (There are actually more callbacks, so the real code is even more bloated.) Ideally, I would do something like this:

- (void) callbackA:(SomeData *)someData {
    if (not_running_on_main_thread) {
    [self performSelectorOnMainThread:@selector(callbackA:)
                       withObject:someData
                    waitUntilDone:NO];
    } else {
        // now running on main thread, work with the results.
    }
}

Questions:

1) how do I do the "not_running_on_main_thread" test?

2) is there any other way to cut down the callbacks bloat?

EDIT: ok, I never read NSThread docs before posting :) looks like [NSThread isMainThread] is what I am looking for. But is there any other way to restructure or make this nicer still?

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(1

梦里南柯 2024-08-25 07:16:02

只需检查 [NSThread isMainThread] 即可。如果您需要执行不同操作的多个回调,则您无能为力。

只有一件事我做了不同的事情,我的代码如下所示:

- (void) callbackA:(SomeData *)someData {
    if (![NSThread isMainThread]) {
        [self performSelectorOnMainThread:@selector(callbackA:)
                       withObject:someData
                    waitUntilDone:NO];
        return;
    }

    // now running on main thread, work with the results.
}

这让我摆脱了整个函数长 else 并使代码更清晰一些。您可以通过这种方式节省一级缩进;-)

Just check for [NSThread isMainThread]. There's nothing more you can do if you need multiple callbacks which do different things.

Only one thing I do differently, my code looks like this:

- (void) callbackA:(SomeData *)someData {
    if (![NSThread isMainThread]) {
        [self performSelectorOnMainThread:@selector(callbackA:)
                       withObject:someData
                    waitUntilDone:NO];
        return;
    }

    // now running on main thread, work with the results.
}

This lets me get rid of the whole-function-long else and make the code a little clearer. And you can save on one indentation level this way ;-)

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文