为什么我们在主线程上使用异步

时间:2019-04-09 07:09:43

标签: ios swift grand-central-dispatch

  

在主线程以外的其他线程上更新UI是一个常见错误,可能会导致错过UI更新,视觉缺陷,数据损坏和崩溃。

     

https://developer.apple.com/documentation/code_diagnostics/main_thread_checker

示例:

let task = URLSession.shared.dataTask(with: url) { (data, response, error) in
   if let data = data {
      DispatchQueue.main.async { // Correct
         self.label.text = "\(data.count) bytes downloaded"
      }
   }
}
task.resume()

我的问题从这里开始- 当我们说.async表示与.main不同时(或不并行)时,我对以上声明感到困惑。有人可以解释我的问题吗?

2 个答案:

答案 0 :(得分:4)

#include <iostream> #include <string> #include <typeinfo> unsigned short operator "" _ush(unsigned long long int a) { return static_cast<unsigned short>(a); } int main() { std::string name; bool equal = typeid(decltype(123_ush)) == typeid(unsigned short); // check that literal is indeed unsigned short std::cout << equal; } 意味着您在主队列中排队一个任务,而无需等待该任务被执行。主队列任务将在操作系统计划的自动自动在主线程上运行。

将每个DispatchQueue.main.async视为工作人员。调用DispatchQueue会在工作人员的TODO列表下添加一个任务,不要等待工作人员完成任务。 .async是在主线程上工作的特定工作程序。

另一方面,DispathQueue.main将阻塞线程,直到任务块执行完毕。您可以在除主线程之外的任何其他线程上调用.sync,因为不得阻塞主线程。

这并不意味着您无法致电.sync。您可以像在非主线程上的任何自定义dispathQueue.sync一样调用DispatchQueue.main.sync。

例如

DispatchQueue.main.sync

可以。

但是

DispatchQueue(label: "bgqueue", qos: .background).async
{ 
    DispatchQueue.main.sync{} 
} 

不是。

DispatchQueue.main.async{ DispatchQueue.main.sync{} } 通常不是很有用。如果您希望在主队列任务之后发生某些事情,您也只需将该“事物”排队到主队列中。如果没有必要,则不值得阻塞线程。

话虽这么说,这是使用.sync时要记住的两个规则,而不管哪个队列正在接收.sync调用:

  1. 永远不要从队列中调用.sync本身,这会导致死锁。
  2. 永远不要从主队列中调用.sync,这会阻塞UI线程。

答案 1 :(得分:2)

我认为您对wb.Activate wb.Sheets("PMCC 1").Select For Each ws In wb.Worksheets ws.Activate index = index + 1 If index <= 10 Then irow = ws.Cells(Rows.Count, 1).End(xlUp).Row newtemp = Replace(ws.Name, " ", "#0") For J = irow To 2 Step -1 If ws.Cells(J, 1) <> newtemp Then ws.Cells(J, 1).EntireRow.Delete End If Next J Else irow = ws.Cells(Rows.Count, 1).End(xlUp).Row newtemp = Replace(ws.Name, " ", "#") For J = irow To 2 Step -1 If ws.Cells(J, 1) <> newtemp Then ws.Cells(J, 1).EntireRow.Delete End If Next J End If Next ws MsgBox ("Deleted") 的工作方式感到困惑。

DispatchQueue只是管理线程池,当我们给它一个代码块执行时,它只是选择一个空闲线程并在其上运行那段代码。

因此,基本上一个线程可以被许多队列使用。队列只是一个任务列表,它管理将来将要执行的所有任务。

因此,基本上在这里,当您执行DispatchQueue时,您只是在指示DispatchQueue.main.async执行代码,而不必等待未决的任务执行。