您好,歡迎來電子發(fā)燒友網(wǎng)! ,新用戶?[免費注冊]

您的位置:電子發(fā)燒友網(wǎng)>源碼下載>通訊/手機編程>

iOS并發(fā)編程中Dispatch Queues的創(chuàng)建與管理的實踐總結(jié)

大?。?/span>0.2 MB 人氣: 2017-10-11 需要積分:1
 導(dǎo)讀:本文為讀《Concurrency Programming Guide》筆記第二篇,在上篇分享了OS X和iOS應(yīng)用開發(fā)中實現(xiàn)任務(wù)異步執(zhí)行的技術(shù)以及應(yīng)注意的事項之后,作者付宇軒(@DevTalking)對Operation對象的設(shè)置與執(zhí)行,以及Dispatch Queues的創(chuàng)建與管理進(jìn)行了實踐總結(jié)。
  系列閱讀
  Operation對象的相關(guān)設(shè)置
  Operation對象除了上文中講到到基本使用方法外還有一些其他的特性,這些特性需要根據(jù)我們的應(yīng)用場景去設(shè)置,設(shè)置的時機在創(chuàng)建Operation對象之后和運行它或者將其放入操作隊列之前,下面讓我們來看看Operation對象還有哪些特性。
  Operation對象之間的依賴
  與GCD不同,Operation Queue不遵循先進(jìn)先出的原則,而且Operation Queue始終是并發(fā)執(zhí)行Operation對象的,所以想讓Operation對象串行執(zhí)行就需要用它的Operation對象依賴特性,該特性可以讓Operation對象將自己與另外一個Operation對象進(jìn)行關(guān)聯(lián),并且當(dāng)關(guān)聯(lián)的Operation對象執(zhí)行完成后才可以執(zhí)行,這樣就達(dá)到了串行執(zhí)行Operation對象的目的。
  我們可以用NSOperation的addDependency方法添加依賴的Operation對象,而且產(chǎn)生依賴的這兩個Operation對象并不要求必須在相同的操作隊列中,但是這種依賴只能是單向的,不能相互依賴。
  importFoundation classTestOperationDependency{func launch() { letblockOperationA = NSBlockOperation(block: { print(“Task in blockOperationA.。.”) sleep(3) }) letblockOperationB = NSBlockOperation(block: { print(“Task in blockOperationB.。.”) sleep(5) }) blockOperationA.addDependency(blockOperationB) letoperationQueue = NSOperationQueue() operationQueue.addOperation(blockOperationA) operationQueue.addOperation(blockOperationB) sleep(10) } } lettestOperationDependency = TestOperationDependency() testOperationDependency.launch()
  上面的示例代碼展示了如何給Operation對象添加依賴,大家可以注釋掉blockOperationA.addDependency(blockOperationB)這一行看看打印結(jié)果有什么區(qū)別。
  Operation對象的優(yōu)先級
  上文中說了,操作隊列里的Operation對象都是并發(fā)執(zhí)行的,如果一個操作隊列中有多個Operation對象,那么誰先執(zhí)行誰后執(zhí)行取決于Operation對象的依賴Operation對象是否已執(zhí)行完成,也就是是否處于準(zhǔn)備執(zhí)行的狀態(tài)。其實Operation對象自身也有優(yōu)先級的屬性,如果有兩個都處于準(zhǔn)備執(zhí)行狀態(tài)的Operation對象,那么優(yōu)先級高的會先執(zhí)行,優(yōu)先級低的后執(zhí)行。每個Operation對象默認(rèn)的優(yōu)先級是NSOperationQueuePriority.Normal級別,我們可以通過設(shè)置queuePriority屬性更改Operation的在隊列中執(zhí)行的優(yōu)先級,優(yōu)先級別有以下五種:
  NSOperationQueuePriority.Normal:正常優(yōu)先級NSOperationQueuePriority.Low:低優(yōu)先級NSOperationQueuePriority.VeryLow:非常低優(yōu)先級NSOperationQueuePriority.High:高優(yōu)先級NSOperationQueuePriority.VeryHigh:非常高優(yōu)先級
  這里我們需要注意一下Operation對象優(yōu)先級的作用域,它只能作用于相同的操作隊列中,不同操作隊列中的Operation對象是不受優(yōu)先級影響的。另外需要注意的是,如果有兩個Operation對象,一個處于準(zhǔn)備執(zhí)行狀態(tài),但優(yōu)先級比較低,另一個處于等待狀態(tài),但優(yōu)先級比較高,那么此時仍然是處于準(zhǔn)備執(zhí)行狀態(tài)的低優(yōu)先級Operation對象先執(zhí)行??梢奜peration對象的優(yōu)先級相互影響需要滿足兩個條件,一是必須處在同一個操作隊列中,另一個是Operation對象都處于準(zhǔn)備執(zhí)行狀態(tài)。
  通過Operation對象修改線程優(yōu)先級
  通常情況下,線程的優(yōu)先級由內(nèi)核自己管理,不過在OS X v10.6及以后的版本和iOS4到iOS7期間,NSOperation多了一個threadPriority屬性,我們可以通過該屬性設(shè)置Operation對象運行所在線程的優(yōu)先級,數(shù)值范圍為0.0到1.0,數(shù)字越高優(yōu)先級越高。不過可能是出于線程安全等方面的考慮,Apple從iOS8開始廢除了該屬性。
  設(shè)置Completion Block
  上篇文章中說過,Operation對象其中的一個特別好的特性就是完成時回調(diào)閉包Completion Block。它的作用不言而喻,就是當(dāng)主要任務(wù)執(zhí)行完成之后做一些收尾的處理工作,我們可以設(shè)置completionBlock屬性給Operation對象添加完成時回調(diào)閉包:
  blockOperationA.completionBlock = { print(“blockOperationA has finished.。.”) }
  執(zhí)行Operation對象
  雖然前面文章的示例中已經(jīng)包含了對Operation對象的執(zhí)行,但是并沒詳細(xì)說明,這節(jié)就說說Operation對象的執(zhí)行。
  使用Operation Queue
  使用Operation Queue操作隊列執(zhí)行Operation對象已然是標(biāo)配選項了,操作隊列在Cocoa框架中對應(yīng)的類是NSOperationQueue,一個操作隊列中可以添加多個Operation對象,但一次到底添加多少Operation對象得根據(jù)實際情況而定,比如應(yīng)用程序?qū)?nèi)存的消耗情況、內(nèi)核的空閑情況等,所以說凡事得有度,不然反而會適得其反。另外需要注意的一點是不論有多少個操作隊列,它們都受制于系統(tǒng)的負(fù)載、內(nèi)核空閑等運行情況,所以說并不是說再創(chuàng)建一個操作隊列就能執(zhí)行更多的Operation對象。
  在使用操作隊列時,我們首先要創(chuàng)建NSOperationQueue的實例:
  letoperationQueue = NSOperationQueue()
  然后通過NSOperationQueue的addOperation方法添加Operation對象:
  operationQueue.addOperation(blockOperationA) operationQueue.addOperation(blockOperationB)
  在OS X v10.6之后和iOS4之后,我們還可以用addOperations:waitUntilFinished:方法添加一組Operation對象:
  operationQueue.addOperations([blockOperationA, blockOperationB], waitUntilFinished: false)
  該方法有兩個參數(shù)
  ops: [NSOperation]:Operation對象數(shù)組。waitUntilFinished wait: Bool:該參數(shù)標(biāo)示這個操作隊列在執(zhí)行Operation對象時是否會阻塞當(dāng)前線程。
  我們還可以通過addOperationWithBlock方法向操作隊列中直接添加閉包,而不需要去創(chuàng)建Operation對象:
  operationQueue.addOperationWithBlock({ print(“The block is running in Operation Queue.。.”) })
  除了以上這幾種添加Operation對象的方法外,還可以通過NSOperationQueue的maxConcurrentOperationCount屬性設(shè)置同時執(zhí)行Operation對象的最大數(shù):
  operationQueue.maxConcurrentOperationCount =2
  如果設(shè)置為1,那么不管該操作隊列中添加了多少Operation對象,每次都只運行一個,而且會按照添加Operation對象的順序去執(zhí)行。所以如果遇到添加到操作的隊列的Operation對象延遲執(zhí)行了,那么通常會有兩個原因:
  添加的Operation對象數(shù)超過了操作隊列設(shè)置的同時執(zhí)行Operation對象的最大數(shù)。延遲執(zhí)行的Operation對象在等待它依賴的Operation對象執(zhí)行完成。
  另外需要的注意的是當(dāng)Operation對象添加到操作隊列中后,不要再更改它任務(wù)中涉及到的任何屬性或者它的依賴,因為到操作隊列中的Operation對象隨時會被執(zhí)行,所以如果你自以為它還沒有被執(zhí)行而去修改它,可能并不會達(dá)到你想要的結(jié)果。
  手動執(zhí)行Operation對象
  除了用操作隊列來執(zhí)行Operation對象以外,我們還可以手動執(zhí)行某個Operation對象,但是這需要我們注意更多的細(xì)節(jié)問題,也要寫更多的代碼去確保Operation對象能正確執(zhí)行。在上篇文章中,我們創(chuàng)建過自定義的Operation對象,其中我們知道有幾個屬性特別需要我們注意,那就是ready、concurrent、executing、finished、cancelled,對應(yīng)Operation對象是否出于準(zhǔn)備執(zhí)行狀態(tài)、是否為異步并發(fā)執(zhí)行的、是否正在執(zhí)行、是否已經(jīng)執(zhí)行完成、是否已被終止。
  這些狀態(tài)在我們使用操作隊列時都不需要理會,都有操作隊列幫我們把控判斷,確保Operation對象的正確執(zhí)行,我們只需要在必要的時候獲取狀態(tài)信息查看而已。但是如果手動執(zhí)行Operation對象,那么這些狀態(tài)都需要我們來把控,因為你手動執(zhí)行一個Operation對象時要判斷它的依賴對象是否執(zhí)行完成,是否被終止了等等,所以并不是簡單的調(diào)用start方法,下面來看看如果正確的手動執(zhí)行Operation對象:
  func performOperation(operation: NSOperation)-》Bool { varresult = falseifoperation.ready && !operation.cancelled { ifoperation.concurrent { operation.start() } else{ NSThread.detachNewThreadSelector(“start”, toTarget: operation, withObject: nil) } result = true} returnresult }
  終止Operation對象執(zhí)行
  一旦Operation對象被添加到操作隊列中,這個Operation對象就屬于這個操作隊列了,并且不能被移除,唯一能讓Operation對象失效的方法就是通過NSOperation的cancel方法終止它執(zhí)行,或者也可以通過NSOperationQueue的cancelAllOperations方法終止在隊列中的所有Operation對象。
  暫停和恢復(fù)操作隊列
  在實際運用中,如果我們希望暫停操作隊列執(zhí)行Operation對象,可以通過設(shè)置NSOperationQueue的suspended屬性為false來實現(xiàn),不過這里要注意的是暫停操作隊列只是暫停執(zhí)行下一個Operation對象,而不是暫停當(dāng)前正在執(zhí)行的Operation對象,將suspended屬性設(shè)置為true后,操作隊列則恢復(fù)執(zhí)行。
  Dispatch Queues
  Dispatch Queue是GCD中的核心功能,它能讓我們很方便的異步或同步執(zhí)行任何被封裝為閉包的任務(wù),它的運作模式與Operation Queue很相似,但是有一點不同的是Dispatch Queue是一種先進(jìn)先出的數(shù)據(jù)結(jié)構(gòu),也就是執(zhí)行任務(wù)的順序永遠(yuǎn)等同于添加任務(wù)時的順序。GCD中已經(jīng)為我們提供了幾種類型的Dispatch Queue,當(dāng)然我們也可以根據(jù)需求自己創(chuàng)建Dispatch Queue,下面我們先來看看Dispatch Queue的類型:
  串行Dispatch Queue:該類型的隊列一次只能執(zhí)行一個任務(wù),當(dāng)前任務(wù)完成之后才能執(zhí)行下一個任務(wù),而且可依任務(wù)的不同而在不同的線程中執(zhí)行,這類隊列通常作為私有隊列使用。這里需要注意的是雖然該類型的隊列一次只能執(zhí)行一個任務(wù),但是可以讓多個串行隊列同時開始執(zhí)行任務(wù),達(dá)到并發(fā)執(zhí)行的任務(wù)的目的。并行Dispatch Queue:該類隊列可同時執(zhí)行多個任務(wù),但是執(zhí)行任務(wù)的順序依然是遵循先進(jìn)先出的原則,同樣可依任務(wù)的不同而在不同的線程中執(zhí)行,這類隊列通常作為全局隊列使用。主Dispatch Queue:該類隊列實質(zhì)上也是一個串行隊列,但是該隊列是一個全局隊列,在該隊列中執(zhí)行的任務(wù)都是在當(dāng)前應(yīng)用的主線程中執(zhí)行的。通常情況下我們不需要自己創(chuàng)建此類隊列。
  Dispatch Queue與Operation Queue相似,都能讓我們更方便的實現(xiàn)并發(fā)任務(wù)的編程工作,并且能提供更優(yōu)的性能,因為我們不再需要編寫關(guān)于線程管理相關(guān)的一大堆代碼,這些完全都有系統(tǒng)接管,我們只需要將注意力放在要執(zhí)行的任務(wù)即可。舉個簡單的例子,如果有兩個任務(wù)需要在不同的線程中執(zhí)行,但是他們之間存在資源競爭的情況,所以需要保證執(zhí)行的先后順序,如果我們自己創(chuàng)建線程實現(xiàn)該場景,那么就務(wù)必要用的線程鎖機制,確保任務(wù)有正確的執(zhí)行順序,這勢必對系統(tǒng)資源的開銷會非常大,如果使用Dispatch Queue,我們只需要將任務(wù)安正確的順序添加到串行隊列中即可,省時省力省資源。
  任務(wù)的載體是閉包
  在使用Dispatch Queue時,需要將任務(wù)封裝為閉包。閉包就是一個函數(shù),或者一個指向函數(shù)的指針,加上這個函數(shù)執(zhí)行的非局部變量,閉包最大的一個特性就是可以訪問父作用域中的局部變量。我們在將任務(wù)封裝為閉包進(jìn)行使用時要注意以下這幾點:
  雖然在閉包中可以使用父作用域中的變量,但是盡可能少的使用父作用域中比較大的變量以及不要在閉包中做類似刪除清空父作用域中變量的行為。當(dāng)將一個封裝好任務(wù)的閉包添加至Dispatch Qeueu中,Dispatch Queue會自動復(fù)制該閉包,并且在執(zhí)行完成后釋放該閉包,所以不同擔(dān)心閉包中一些值的變化問題,以及資源釋放問題。雖然使用Dispatch Queue執(zhí)行并發(fā)異步任務(wù)很方便,但是創(chuàng)建和執(zhí)行閉包還是有一定資源開銷的,所以盡量不要使用Dispatch Queue執(zhí)行一些很小的任務(wù),要物有所值。如果確實有很小的任務(wù)需要并發(fā)異步執(zhí)行,那么使用NSThread的detachNewThreadSelector方法或NSObject的performSelectorInBackground方法去執(zhí)行也未必不可。如果同一個隊列中的多個任務(wù)之間需要共享數(shù)據(jù),那么應(yīng)該使用隊列上下文去存儲數(shù)據(jù),供不同的任務(wù)訪問。如果閉包中的任務(wù)創(chuàng)建了不少對象,那么應(yīng)該考慮將整個任務(wù)邏輯代碼放在autoreleasepool中,雖然Dispatch Queue中也有自動釋放池,但是你不能保證它每次釋放的時間,所以咱們自己再加一個要來的更保險一些。
  創(chuàng)建與管理Dispatch Queues
  在使用Dispatch Queue之前,我們首先需要考慮應(yīng)該創(chuàng)建什么類型的Dispatch Queue,如何進(jìn)行配置等,這一節(jié)就來說一說如何創(chuàng)建和管理Dispatch Queue。
  全局并發(fā)Dispatch Queue
  并發(fā)隊列的好處人人皆知,可以方便的同時處理多個任務(wù),在GCD中并發(fā)Dispatch Queue同樣遵循先進(jìn)先出的原則,但這只是在運行時適用,如果有個任務(wù)在并發(fā)隊列中還沒輪到它執(zhí)行,那么此時完全可以移除它,而不必等它前面的任務(wù)執(zhí)行完成之后。至于并發(fā)隊列中沒次有多少個任務(wù)在執(zhí)行,這個恐怖在每一秒都在變化,因為影響它的因素有很多,所以之前說過,盡量不要移除移除已經(jīng)添加進(jìn)隊列的任務(wù)。
  OS X和iOS系統(tǒng)為我們提供了四種全局并發(fā)Dispatch Queue,所謂全局隊列,就是我們不需要理會它們的保留和釋放問題,而且不需要專門創(chuàng)建它。與其說是四種不如說是一種全局并發(fā)隊列的四種不同優(yōu)先級,因為它們之間唯一的不同之處就是隊列優(yōu)先級不同。與Operation Queue不同,在GCD中,Dispatch Queue只有四種優(yōu)先級:
  DISPATCH_QUEUE_PRIORITY_HIGH:高優(yōu)先級。DISPATCH_QUEUE_PRIORITY_DEFAULT:默認(rèn)優(yōu)先級,低于高優(yōu)先級。DISPATCH_QUEUE_PRIORITY_LOW:低優(yōu)先級,低于高優(yōu)先級和默認(rèn)優(yōu)先級。DISPATCH_QUEUE_PRIORITY_BACKGROUND:后臺優(yōu)先級,低于高優(yōu)先級和后臺線程執(zhí)行的任務(wù)。
  我們可以通過dispatch_get_global_queue函數(shù)再根據(jù)不同的優(yōu)先級獲取不同的全局并發(fā)隊列,類型為dispatch_queue_t:
  lethighPriorityQueue = dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_HIGH, 0) letdefaultPriorityQueue = dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0)
  我們在使用全局并發(fā)隊列的時候不需要保留隊列的引用,隨時要用隨時用該函數(shù)獲取即可。當(dāng)然我們也可以通過dispatch_queue_create函數(shù)自己創(chuàng)建隊列:
  letconcurrentQueue = dispatch_queue_create(“com.example.MyConcurrentQueue”, DISPATCH_QUEUE_CONCURRENT)
  從上面代碼可以看到,dispatch_queue_create函數(shù)有兩個參數(shù),第一個為隊列的名稱,第二個為隊列類型,串行隊列為DISPATCH_QUEUE_SERIAL,并發(fā)隊列為DISPATCH_QUEUE_CONCURRENT。
  串行Dispatch Queue
  串行隊列可以讓我們將任務(wù)按照一定順序執(zhí)行,能更優(yōu)的處理多個任務(wù)之間的資源競爭問題,比線程鎖機制有更小的資源開銷和更好的性能,并且不會產(chǎn)生死鎖的問題。
  系統(tǒng)也為我們提供了一個串行隊列,我們可以通過dispatch_get_main_queue函數(shù)獲?。?br />   letmainQueue = dispatch_get_main_queue()
  該隊列與當(dāng)前應(yīng)用的主線程相關(guān)聯(lián)。當(dāng)然我們也可以自己創(chuàng)建串行隊列:
  letserialQueueA = dispatch_queue_create(“com.example.MySerialQueueA”, DISPATCH_QUEUE_SERIAL) // 或者letserialQueueB = dispatch_queue_create(“com.example.MySerialQueueB”, nil)
  dispatch_queue_create函數(shù)的第二個參數(shù)如果為nil則默認(rèn)創(chuàng)建串行隊列。當(dāng)我們創(chuàng)建好串行隊列后,系統(tǒng)會自動將創(chuàng)建好的隊列與當(dāng)前應(yīng)用的主線程進(jìn)行關(guān)聯(lián)。
  獲取當(dāng)前隊列
  如果需要驗證或者測試當(dāng)前隊列,我們可以通過dispatch_get_current_queue函數(shù)獲取當(dāng)前隊列。如果在閉包中調(diào)用,返回的是該閉包所在的隊列,如果在閉包外調(diào)用,返回的則是默認(rèn)的并發(fā)隊列。不過該函數(shù)在OS X v10.10中和Swift中都不能使用了,取而代之的是通過DISPATCH_CURRENT_QUEUE_LABEL屬性的get方法。
  擅用隊列上下文
  很多情況下,同一個隊列中的不同任務(wù)之間需要共享數(shù)據(jù),尤其像串行隊列中的任務(wù),可能由多個任務(wù)對某個變量進(jìn)行處理,或者都需要使用到某個對象,這時就要用到隊列上下文:
  import Foundation classTestDispatchQueue{func launch() { let serialQueue = dispatch_queue_create(“com.example.MySerialQueue”, DISPATCH_QUEUE_SERIAL) dispatch_set_context(serialQueue, unsafeBitCast(0, UnsafeMutablePointer《Int》.self)) dispatch_async(serialQueue, { vartaskCount = unsafeBitCast(dispatch_get_context(serialQueue), Int.self) taskCount++ print(“TaskA in the dispatch queue.。.and The number of task in queue is \(taskCount)”) dispatch_set_context(serialQueue, unsafeBitCast(taskCount, UnsafeMutablePointer《Int》.self)) sleep(1) }) dispatch_async(serialQueue, { vartaskCount = unsafeBitCast(dispatch_get_context(serialQueue), Int.self) taskCount++ print(“TaskB in the dispatch queue.。.and The number of task in queue is \(taskCount)”) dispatch_set_context(serialQueue, unsafeBitCast(taskCount, UnsafeMutablePointer《Int》.self)) }) sleep(3) } } let testDispatchQueue = TestDispatchQueue() testDispatchQueue.launch()
  從上面的代碼示例中可以看到,在執(zhí)行代碼點,我們用dispatch_set_context函數(shù)向serialQueue隊列的上下文環(huán)境中設(shè)置了一個Int類型的變量,初始值為0。該函數(shù)有兩個參數(shù),第一個是目標(biāo)隊列,第二個參數(shù)是上下文數(shù)據(jù)的指針。然后在閉包中我們使用dispatch_get_context函數(shù)獲取上下文數(shù)據(jù)進(jìn)行進(jìn)一步的處理。除了基本類型,我們也可以將自定義的類放入隊列上下文中:
  importFoundation class Contact: NSObject { letname =“DevTalking”letmobile =“10010”} class TestDispatchQueue { letcontact =Contact() func launch() { letserialQueue =dispatch_queue_create(“com.example.MySerialQueue”, DISPATCH_QUEUE_SERIAL) dispatch_set_context(serialQueue, unsafeBitCast(contact, UnsafeMutablePointer《Void》.self)) dispatch_async(serialQueue, { letcontact =unsafeBitCast(dispatch_get_context(serialQueue), Contact.self) print(“The name is \(contact.name)”) sleep(1) }) dispatch_async(serialQueue, { letcontact =unsafeBitCast(dispatch_get_context(serialQueue), Contact.self) print(“The name is \(contact.mobile)”) }) sleep(3) } } lettestDispatchQueue =TestDispatchQueue() testDispatchQueue.launch()
  關(guān)于unsafeBitCast函數(shù)和Swift中指針的用法在這里可以有所參考。
  隊列的收尾工作
  雖然在ARC時代,資源釋放的工作已經(jīng)基本不需要我們手動去做了,但有些時候因為系統(tǒng)釋放資源并不是很及時,也會造成內(nèi)存移除等問題,所以在一些情況下我們還是需要進(jìn)行手動釋放資源的工作,必入添加autoreleasepool保證資源及時釋放等。Dispatch Queue也給我們提供了這樣的機會(機會針對于ARC時代,在MRC時代是必須要做的),那就是Clean Up Function清理掃尾函數(shù),當(dāng)隊列被釋放時,或者說引用計數(shù)為0時會調(diào)用該函數(shù),并且將上下文指針也傳到了該函數(shù),以便進(jìn)行清理工作:
  importFoundation class Contact: NSObject { letname =“DevTalking”letmobile =“10010”} class TestDispatchQueue { letcontact =Contact() func testCleanUpFunction() { launch() sleep(15) } func launch() { letserialQueue =dispatch_queue_create(“com.example.MySerialQueue”, DISPATCH_QUEUE_SERIAL) dispatch_set_context(serialQueue, unsafeBitCast(contact, UnsafeMutablePointer《Void》.self)) dispatch_set_finalizer_f(serialQueue, myFinalizerFunction()) dispatch_async(serialQueue, { letcontact =unsafeBitCast(dispatch_get_context(serialQueue), Contact.self) print(“The name is \(contact.name)”) sleep(1) }) dispatch_async(serialQueue, { letcontact =unsafeBitCast(dispatch_get_context(serialQueue), Contact.self) print(“The name is \(contact.mobile)”) }) sleep(3) } func myFinalizerFunction() -》 dispatch_function_t { return{ context inletcontact =unsafeBitCast(context, Contact.self) print(“The name is \(contact.name) and the mobile is \(contact.mobile), The serialQueue has been released and we need clean up context data.”) // TODO.。. } } } lettestDispatchQueue =TestDispatchQueue() testDispatchQueue.testCleanUpFunction()
  從上面的代碼示例中可以看到當(dāng)給隊列設(shè)置完上下文時,我們使用了dispatch_set_finalizer_f函數(shù)給隊列設(shè)置清理函數(shù),dispatch_set_finalizer_f函數(shù)有兩個參數(shù),第一個是目標(biāo)隊列,第二個參數(shù)是類型為dispatch_function_t的函數(shù)指針,也就是清理函數(shù),上下文數(shù)據(jù)指針是該函數(shù)唯一的參數(shù)。在上面代碼中,我們添加了myFinalizerFunction函數(shù)作為清理函數(shù),在該函數(shù)中獲得上下文數(shù)據(jù),然后進(jìn)行后續(xù)的清理工作。
?

非常好我支持^.^

(0) 0%

不好我反對

(0) 0%

      發(fā)表評論

      用戶評論
      評價:好評中評差評

      發(fā)表評論,獲取積分! 請遵守相關(guān)規(guī)定!

      ?