32

我看过这个代码片段:

dispatch_async(dispatch_get_main_queue(), ^{
    [self doSomeNetworkStuff];
});

这对我来说似乎没有多大意义。

编辑:澄清我的问题的条件:

  • 调用dispatch_async是从主线程执行的。
  • 发送的消息doSomeNetworkStuff是繁重的工作任务。
  • ...而且不仅是 UI 更新任务。

调度,当然,但使用主队列只会将调度的任务拉回 ui 线程并阻止它。

请问,我错过了什么吗?谢谢。

4

6 回答 6

38

dispatch_async让您的应用程序在许多队列上运行任务,因此您可以提高性能。但是所有与 UI 交互的东西都必须在主线程上运行。您可以在主线程之外运行与 UI 无关的其他任务以提高性能。

dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{

  //Add some method process in global queue - normal for data processing

    dispatch_async(dispatch_get_main_queue(), ^(){
    //Add method, task you want perform on mainQueue
    //Control UIView, IBOutlet all here

    });

 //Add some method process in global queue - normal for data processing

});
于 2013-03-02T02:21:38.093 回答
8

斯威夫特 3

DispatchQueue.global(attributes: .qosBackground).async {
    print("This is run on the background queue")

    DispatchQueue.main.async {
        print("This is run on the main queue, after the previous code in outer block")
    }
}
于 2016-06-18T17:26:32.137 回答
6

当你想做一些 Webservicecall 或一些你调度异步调用的事情时,如下所示:

dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT,0),^{
        //Call your webservice here , your app will not freeze at all  
});

现在,假设你想从你的调度线程更新或推送一个 ViewController,如果你直接从这个推送视图控制器,应用程序将会或可能会崩溃,因为这样的 UI 更新应该在应用程序的主线程中完成,下面是这个的答案然后。

dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT,0),^{
       //Call your webservice here , your app will not freeze at all

       //To update UIFrom dispatched Thread:

       dispatch_async(dispatch_get_main_queue,^{   

       //Push view controller here
});

});

详情请访问:blackberrymastercracks.blogspot.in

于 2013-05-28T12:06:11.713 回答
5

这取决于调用此代码的位置。意味着如果它从主队列调用,那么它没有意义。(注意:它不会导致崩溃,但只会在主队列中添加一个任务)。

如果此代码是在后台线程中编写的,那么这就是应用程序的汇聚点。就像您在后台线程中从 Web 服务获取数据然后想要在 UI 上更新它然后您可以调用它。

-(void) backgroundThreadFunction {

     //Some stuff on background thread. 

     dispatch_async(dispatch_get_main_queue(), ^{
         //Wants to update UI or perform any task on main thread.    
         [self doSomeNetworkStuff];
     });
}

您可以在苹果文档https://developer.apple.com/library/ios/documentation/General/Conceptual/ConcurrencyProgrammingGuide/OperationQueues/OperationQueues.html 或从这个答案中找到更多详细信息https://stackoverflow.com/a/ 19822753/505735

如果仍然不清楚,请给我发帖。我会写一个详细的答案。

于 2014-05-09T09:57:55.783 回答
3

您通常会dispatch_async在后台线程上运行的另一个调用中看到该语法。这是因为 UI 的所有更新都应该发生在主线程上,而不是后台。

于 2013-03-02T02:21:45.820 回答
0

我忘记了这个问题,但由于它仍然受到关注,我将发布对此的答案(使用 swift)

假设:我知道 UI 工作必须在主线程上完成。

//
// We are on the main thread here.
// The following will schedule the closure on the main thread after ALL other 
//   routines currently scheduled on the main thread are done. 
//
DispatchQueue.main.async {
    //
    // So here we are back on the main thread AFTER all routines on the main 
    //   thread have completed.
    // 
    // If the following call does NOT dispatch onto a background thread 
    //    it will block the UI and it was really bad programming.
    // 
    // Thus, for now and for the benefit of the doubt, let's assume 
    //   `doSomeNetworkStuff()` DOES dispatch to a background thread.
    //   
    // This can only make sense if the the func `doSomeNetworkStuff()` 
    //   relies on results of code paths following this current 
    //   `DispatchQueue.main.async(... we are here ...)`.
    //
    // If `doSomeNetworkStuff()` does NOT depend on any other code paths:
    //   Why not directly scheduling it directly on a background thread? 
    //   Which is unnecessary, as as stated above it MUST dispatch on to the
    //     background anyways.
    // 
    // Moreover, there is few possibility that `doSomeNetworkStuff()` does 
    //   depend on other codepaths, because `self` is already captured by 
    //   the closure.
    //
    self.doSomeNetworkStuff()
}

恕我直言,将所有这些放在一起,原始代码没有多大意义。它可以替换为:

// We are on the main thread here
self.doSomeNetworkStuff()

原始的异步分派到主线程然后分派到后台应该是浪费和混乱的(显然)。

不幸的是,我不能再用原始代码库来尝试这个了。

我在这里错过了一个想法吗?

于 2020-02-02T18:45:04.657 回答