performSelectorOnMainThread和主队列上的dispatch_async有什么区别?

时间:2022-05-15 21:00:00

I was having problems modifying a view inside a thread. I tried to add a subview but it took around 6 or more seconds to display. I finally got it working, but I don't know how exactly. So I was wondering why it worked and what's the difference between the following methods:

我在线程内修改视图时遇到了问题。我试图添加一个子视图,但它花了大约6秒或更多秒来显示。我终于把它修好了,但我不知道具体是怎么回事。所以我想知道它为什么有效,以及以下方法的区别:

//this worked -added the view instantly
dispatch_async(dispatch_get_main_queue(), ^{
    //some UI methods ej
    [view addSubview: otherView];
}

//this took around 6 or more seconds to display
[viewController performSelectorOnMainThread:@selector(methodThatAddsSubview:) withObject:otherView
 waitUntilDone:NO];

//Also didnt work: NSNotification methods -  took also around 6 seconds to display
//the observer was in the viewController I wanted to modify
//paired to a method to add a subview.
[[NSNotificationCenter defaultCenter] postNotificationName:
 @"notification-identifier" object:object];

For reference this were called inside this Completetion Handler of the class of the ACAccountStore.

作为参考,这在ACAccountStore类的Completetion处理程序中被调用。

accountStore requestAccessToAccountsWithType:accountType withCompletionHandler:^(BOOL granted, NSError *error) {
            if(granted) {
            //my methods were here
            }
}

Edit: When I say it didn't work I meant it took about 6 seconds to display the view I added.

编辑:当我说它不工作时,我的意思是它花了大约6秒来显示我添加的视图。

3 个解决方案

#1


69  

By default, -performSelectorOnMainThread:withObject:waitUntilDone: only schedules the selector to run in the default run loop mode. If the run loop is in another mode (e.g. the tracking mode), it won't run until the run loop switches back to the default mode. You can get around this with the variant -performSelectorOnMainThread:withObject:waitUntilDone:modes: (by passing all the modes you want it to run in).

默认情况下,-performSelectorOnMainThread:withObject:waitUntilDone:只安排选择器以默认的运行循环模式运行。如果运行循环处于另一种模式(例如跟踪模式),则在运行循环切换回默认模式之前不会运行。您可以使用变体-performSelectorOnMainThread:withObject:waitUntilDone:模式:(通过传递您希望它运行的所有模式)。

On the other hand, dispatch_async(dispatch_get_main_queue(), ^{ ... }) will run the block as soon as the main run loop returns control flow back to the event loop. It doesn't care about modes. So if you don't want to care about modes either, dispatch_async() may be the better way to go.

另一方面,设置(dispatch_get_main_queue()、^ {…当主运行循环将控制流返回到事件循环时,将运行该块。它不关心模式。因此,如果您也不想关心模式,那么dispatch_async()可能是更好的方法。

#2


1  

It's likely because performSelectorOnMainThread:withObject:waitUntilDone: queues the message with common run loop modes. According to Apple's Concurrency Programming Guide, the main queue will interleave queued tasks with other events from the app's run loop. Thus, if there are other events to be processed in the event queue, the queued blocks in the dispatch queue may be run first, even though they were submitted later.

这很可能是因为performSelectorOnMainThread:withObject:waitUntilDone:用常见的运行循环模式来对消息进行排队。根据苹果的并发编程指南,主队列将把排队的任务与应用程序运行循环中的其他事件交织在一起。因此,如果在事件队列中有其他事件要处理,那么可以先运行分派队列中的队列块,即使它们是稍后提交的。

This article is a superb explanation to performSelectorOnMainThread vs. dispatch_async, which also answers the above question.

本文对performSelectorOnMainThread与dispatch_async进行了极好的解释,也回答了上面的问题。

#3


0  

Did you try thePerformSelectorOnMainThread with waitUntilDone=YES

你试过用waitUntilDone的performselectoronmainthread吗

Eg:

例如:

Code:

代码:

[viewController performSelectorOnMainThread:@selector(methodThatAddsSubview:) withObject:otherView waitUntilDone:YES];

I think that might solve the issue as of why the PerformSelectorOnMainThread takes so long to respond.

我认为这可以解决为什么PerformSelectorOnMainThread需要这么长时间才能做出响应的问题。

#1


69  

By default, -performSelectorOnMainThread:withObject:waitUntilDone: only schedules the selector to run in the default run loop mode. If the run loop is in another mode (e.g. the tracking mode), it won't run until the run loop switches back to the default mode. You can get around this with the variant -performSelectorOnMainThread:withObject:waitUntilDone:modes: (by passing all the modes you want it to run in).

默认情况下,-performSelectorOnMainThread:withObject:waitUntilDone:只安排选择器以默认的运行循环模式运行。如果运行循环处于另一种模式(例如跟踪模式),则在运行循环切换回默认模式之前不会运行。您可以使用变体-performSelectorOnMainThread:withObject:waitUntilDone:模式:(通过传递您希望它运行的所有模式)。

On the other hand, dispatch_async(dispatch_get_main_queue(), ^{ ... }) will run the block as soon as the main run loop returns control flow back to the event loop. It doesn't care about modes. So if you don't want to care about modes either, dispatch_async() may be the better way to go.

另一方面,设置(dispatch_get_main_queue()、^ {…当主运行循环将控制流返回到事件循环时,将运行该块。它不关心模式。因此,如果您也不想关心模式,那么dispatch_async()可能是更好的方法。

#2


1  

It's likely because performSelectorOnMainThread:withObject:waitUntilDone: queues the message with common run loop modes. According to Apple's Concurrency Programming Guide, the main queue will interleave queued tasks with other events from the app's run loop. Thus, if there are other events to be processed in the event queue, the queued blocks in the dispatch queue may be run first, even though they were submitted later.

这很可能是因为performSelectorOnMainThread:withObject:waitUntilDone:用常见的运行循环模式来对消息进行排队。根据苹果的并发编程指南,主队列将把排队的任务与应用程序运行循环中的其他事件交织在一起。因此,如果在事件队列中有其他事件要处理,那么可以先运行分派队列中的队列块,即使它们是稍后提交的。

This article is a superb explanation to performSelectorOnMainThread vs. dispatch_async, which also answers the above question.

本文对performSelectorOnMainThread与dispatch_async进行了极好的解释,也回答了上面的问题。

#3


0  

Did you try thePerformSelectorOnMainThread with waitUntilDone=YES

你试过用waitUntilDone的performselectoronmainthread吗

Eg:

例如:

Code:

代码:

[viewController performSelectorOnMainThread:@selector(methodThatAddsSubview:) withObject:otherView waitUntilDone:YES];

I think that might solve the issue as of why the PerformSelectorOnMainThread takes so long to respond.

我认为这可以解决为什么PerformSelectorOnMainThread需要这么长时间才能做出响应的问题。