主线程冲突/计时问题-GCD-iPhone
我的应用程序中有以下调度队列:主线程冲突/计时问题-GCD-iPhone,iphone,objective-c,multithreading,thread-safety,grand-central-dispatch,Iphone,Objective C,Multithreading,Thread Safety,Grand Central Dispatch,我的应用程序中有以下调度队列: 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_
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方法请求访问现已解除分配的类中的变量时,应用程序崩溃
有人能就如何解决这个时间问题提供建议吗
先谢谢你
这是错误的方式:
浮点数组计数=[PointerStorage数组计数]
-正确的方法:
NSUinteger arrayCountInt = [pointerStorageArray count];
NSNumber *arrayCountNumber = [NSNumber numberWithUnsignedInteger:arrayCountInt]
float arrayCount = [arrayCountNumber floatValue];
您使用两种不同的机制来调度主线程中的任务:dispatch_asyc和performSelectorInMainThread:withObject:waitUntilDone:。每个机制都使用自己的队列,由主运行循环读取 读取这些队列的顺序未定义。因此,由performSelectorInMainThread:withObject:waitUntilDone调度的任务可以在使用dispatch_async调度的任务之后或之前执行,而不管先调度哪个任务 您应该更新tidyUpProgress:以使用dispatch\u async。那么订单就有保证了
此外,在释放一个对象后,您应该始终使保存该对象引用的变量为空。只是一个想法-尝试在分派中重命名该变量:
dispatch_queue_t mainqueue = dispatch_get_main_queue();
dispatch_async(mainqueue, ^ {
实际上,它是完全有效的,这里显示的所有额外步骤都是不必要的。另外,这个答案并没有解决这个问题。我过去在类型转换中有一些奇怪的错误,比如,这就是为什么我建议尝试这样做的原因—但似乎没有帮助—如果我将TidyApprogress更改为以下内容,我仍然会遇到同样的问题dispatch_queue_t queue=dispatch_get_main_queue dispatch_asyncqueue,^{[tidyUpMonitorDelegate Model3DTidyApprogressUpdate];}哪一个?tidyUpMonitorDelegate中的那个还是另一个?啊,它工作得很好!你真是个天才,很简单,谢谢你!在块中,它会在块中使用的变量的注释范围之外进行“复制”或保留,以防它们在块执行之前消失——因此我在本例中进行了计算,因为您的变量具有相同的名称,而块不知道您实际上要调用哪一个!