1

我有以下的調度隊列我的應用程序:主線程衝突/計時問題 - GCD - iPhone

dispatch_queue_t queue = dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0); 
dispatch_async(queue,^{ 

[activeModel freeUpMallocedData]; 

// UI Updates have to be made on the main thread, so request from GCD. 

dispatch_queue_t queue = dispatch_get_main_queue(); 
dispatch_async(queue,^{ 

[mainViewController removeTidyUpScreen]; 
[mainViewController showSceneList]; 
[activeModel release]; 

}); 
}); 

的freeUpMallocedData方法更新了UI進度視圖:

- (void) freeUpMallocedData { 

// Calculate the percentage increase for each item in the pointerStorageArray as it is released so we can update the Progress Screen. 

float arrayCount = [pointerStorageArray count]; 
float incrementCounter = 1/arrayCount; // Caculates 1% of pointerStorageArray 
float newValue = incrementCounter; 
int stepCounter = 0; 

NSString * message; 

// Now iterate through the pointerStorageArray and free all malloced memory. 

for (NSValue * value in pointerStorageArray) { 

    stepCounter ++; 
    newValue = newValue + incrementCounter; 

    message = [NSString stringWithFormat:@"Freeing Up Memory (%d of %d) ...", stepCounter, (int)arrayCount]; 

    free(value); 

    [self tidyUpProgress:message amount:newValue]; 

} 

} 

的tidyUpProgress方法,然後執行在主線程上。

- (void) tidyUpProgress: (NSString *) progressMsg amount: (float) amount { 
if (tidyUpMonitorDelegate) { 
    tidyUpProgressMsg = progressMsg; 
    tidyUpProgressAmount = amount; 
    [tidyUpMonitorDelegate performSelectorOnMainThread:@selector(model3DTidyUpProgressUpdate) withObject:nil waitUntilDone:NO]; 
} 
} 

- (void) model3DTidyUpProgressUpdate { 
progressView.progress = app.activeModel.tidyUpProgressAmount; 
loadingStatus.text = app.activeModel.tidyUpProgressMsg; 
} 

問題是,當freeUpMallocedData方法完成時,應用程序崩潰。原因是我的初始分派隊列繼續請求主隊列,然後釋放activeView。這似乎是在tidyUpMonitorDelegate執行其最後一次更新之前劫持線程 - 當它返回主線程時,activeView已經釋放,因此應用程序崩潰,因爲model3DTidyUpProgresUpdate方法正在請求訪問已經存在的類中的變量dealloced。

任何人都可以建議如何解決這個時間問題?

預先感謝您。

回答

3

只是一個想法 - 嘗試重命名調度裏面的變量:

dispatch_queue_t mainqueue = dispatch_get_main_queue(); 
dispatch_async(mainqueue,^{ 
-3
  • 這是錯誤的方式:

    浮子arrayCount = [pointerStorageArray計數];

-correct方式:

NSUinteger arrayCountInt = [pointerStorageArray count]; 
NSNumber *arrayCountNumber = [NSNumber numberWithUnsignedInteger:arrayCountInt] 
float arrayCount = [arrayCountNumber floatValue]; 
+3

其實,這是完全合法的,在這裏顯示的所有額外的步驟是不必要的。另外,這個答案沒有解決問題的問題。 – gschandler 2011-12-17 09:12:16

+0

我在過去一些奇怪的類型轉換這樣的錯誤,這就是爲什麼我建議嘗試做 – user170317 2011-12-17 09:14:20

0

您可以使用兩種不同的機制安排在主線程任務:dispatch_asyc和performSelectorInMainThread:withObject:waitUntilDone :.每個機制使用它自己的隊列,這是由主運行循環讀取的。

這些隊列被讀取的順序是未定義的。因此,可以在使用dispatch_async調度的任務之後(或之前)執行由performSelectorInMainThread:withObject:waitUntilDone調度的任務,而不管首先調度哪個任務。

您應該更新tidyUpProgress:使用dispatch_async。那麼訂單將得到保證。

而且,在釋放一個對象之後,您應該始終取消保存對該對象引用的變量。

+0

謝謝 - 但似乎沒有幫助 - 如果我改變tidyUpProgress到以下我仍然有同樣的問題dispatch_queue_t隊列= dispatch_get_main_queue() dispatch_async(queue,^ {tidyUpMonitorDelegate model3DTidyUpProgressUpdate]; }); } – GuybrushThreepwood 2011-12-17 12:19:53