gpt4 book ai didi

iphone - 初学者在 iPhone 上常犯的多线程错误

转载 作者:行者123 更新时间:2023-12-03 18:34:34 26 4
gpt4 key购买 nike

我刚刚在我的应用程序中引入了多线程,只是为了让一个愚蠢的 UIActivityIndi​​catorView 工作。好吧,事件指示器可以工作,好吧 - 但现在我的应用程序有时会崩溃,有时不会 - 在其他受控条件下......我需要弄清楚这一点,但不知道从哪里开始寻找......

那么,初学者在 iPhone 上使用多线程时常犯的常见错误有哪些?请具体回答。谢谢你的时间。

更新:我添加了有问题的来源以供引用。

//--------------------Where the multithreading starts------------------------


-(IBAction)processEdits:(id)sender
{
//Try to disable the UI to prevent user from launching duplicate threads
[self.view setUserInteractionEnabled:NO];

//Initialize indicator (delcared in .h)
myIndicator = [[UIActivityIndicatorView alloc] initWithFrame:CGRectMake(155, 230, 20, 20)];
myIndicator.activityIndicatorViewStyle = UIActivityIndicatorViewStyleWhite;
[self.view addSubview:myIndicator];
[self.view bringSubviewToFront:myIndicator];
[myIndicator startAnimating];


//Prepare and set properties of the NEXT modal view controller to switch to
controller = [[EndViewController alloc] initWithNibName:@"EndViewController" bundle:nil];

controller.delegate = self;

[self performSelectorInBackground:@selector(threadWork:) withObject:nil];


}



//-----------------------------THE THREAD WORK--------------------------------


-(IBAction)threadWork:(id)sender{

NSAutoreleasePool * pool;
NSString * status;

pool = [[NSAutoreleasePool alloc] init];
assert(pool != nil);


//The image processing work that takes time
controller.photoImage = [self buildPhoto];

//Stop the UIActivityIndicatorView and launch next modal view
[self performSelectorOnMainThread:@selector(stopSpinner:)withObject:nil waitUntilDone:NO];

[pool drain];


}




//-------------------Most of the WORKLOAD called in above thread ------------------------



-(UIImage*)buildPhoto
{
/*
This is the work performed in the background thread. Process photos that the user has edited and arrange them into a UIView to be finally flattened out into a new UIImage. Problem: UI usually changes for some reason during this work.
*/

UIView* photoContainerView = [[UIView alloc] initWithFrame:CGRectMake(0,0,975,1300)];
photoContainerView.backgroundColor = [UIColor whiteColor];
UIImage* purikuraFlattened;
int spacerX = 10;
int spacerY = 10;

switch (myPattern) {

case 0:

photoContainerView.frame = CGRectMake(0, 0, 320, 427);
layoutSingle = [[UIImageView alloc] initWithFrame:CGRectMake(photoContainerView.frame.origin.x,photoContainerView.frame.origin.y,320,427)];
[photoContainerView addSubview:layoutSingle];
layoutSingle.image = editPhotoData1;

break;


case 1:

layoutAimg1 = [[UIImageView alloc] initWithFrame:CGRectMake(photoContainerView.frame.origin.x+spacerX, photoContainerView.frame.origin.y+spacerY, 427, 320)];
layoutAimg2 = [[UIImageView alloc] initWithFrame:CGRectMake(photoContainerView.frame.origin.x+spacerX+427, photoContainerView.frame.origin.y+spacerY, 427, 320)];
layoutAimg3 = [[UIImageView alloc] initWithFrame:CGRectMake(photoContainerView.frame.origin.x+spacerX, photoContainerView.frame.origin.y+spacerY+320, 427, 320)];
layoutAimg4 = [[UIImageView alloc] initWithFrame:CGRectMake(photoContainerView.frame.origin.x+spacerX+427, photoContainerView.frame.origin.y+spacerY+320, 427, 320)];
layoutAimg5 = [[UIImageView alloc] initWithFrame:CGRectMake(photoContainerView.frame.origin.x+spacerX, photoContainerView.frame.origin.y+spacerY+(320*2), 427, 320)];
layoutAimg6 = [[UIImageView alloc] initWithFrame:CGRectMake(photoContainerView.frame.origin.x+spacerX+427, photoContainerView.frame.origin.y+spacerY+(320*2), 427, 320)];
layoutAimg7 = [[UIImageView alloc] initWithFrame:CGRectMake(photoContainerView.frame.origin.x+spacerX, photoContainerView.frame.origin.y+spacerY+(320*3), 427, 320)];
layoutAimg8 = [[UIImageView alloc] initWithFrame:CGRectMake(photoContainerView.frame.origin.x+spacerX+427, photoContainerView.frame.origin.y+spacerY+(320*3), 427, 320)];

[photoContainerView addSubview:layoutAimg1];
[photoContainerView addSubview:layoutAimg2];
[photoContainerView addSubview:layoutAimg3];
[photoContainerView addSubview:layoutAimg4];
[photoContainerView addSubview:layoutAimg5];
[photoContainerView addSubview:layoutAimg6];
[photoContainerView addSubview:layoutAimg7];
[photoContainerView addSubview:layoutAimg8];


if(myShots == 1){

rotPhoto1 = [self rotateImage:editPhotoData1.size:editPhotoData1];

layoutAimg1.image = rotPhoto1;
layoutAimg2.image = rotPhoto1;
layoutAimg3.image = rotPhoto1;
layoutAimg4.image = rotPhoto1;
layoutAimg5.image = rotPhoto1;
layoutAimg6.image = rotPhoto1;
layoutAimg7.image = rotPhoto1;
layoutAimg8.image = rotPhoto1;



}else if(myShots == 2){


rotPhoto1 = [self rotateImage:editPhotoData1.size: editPhotoData1];
rotPhoto2 = [self rotateImage:editPhotoData2.size: editPhotoData2];

layoutAimg1.image = rotPhoto1;
layoutAimg2.image = rotPhoto2;
layoutAimg3.image = rotPhoto2;
layoutAimg4.image = rotPhoto1;
layoutAimg5.image = rotPhoto1;
layoutAimg6.image = rotPhoto2;
layoutAimg7.image = rotPhoto2;
layoutAimg8.image = rotPhoto1;


}else if(myShots == 4){

rotPhoto1 = [self rotateImage:editPhotoData1.size: editPhotoData1];
rotPhoto2 = [self rotateImage:editPhotoData2.size: editPhotoData2];
rotPhoto3 = [self rotateImage:editPhotoData3.size: editPhotoData3];
rotPhoto4 = [self rotateImage:editPhotoData4.size: editPhotoData4];

layoutAimg1.image = rotPhoto1;
layoutAimg2.image = rotPhoto2;
layoutAimg3.image = rotPhoto3;
layoutAimg4.image = rotPhoto4;
layoutAimg5.image = rotPhoto1;
layoutAimg6.image = rotPhoto2;
layoutAimg7.image = rotPhoto3;
layoutAimg8.image = rotPhoto4;


}
break;

}


UIGraphicsBeginImageContext(photoContainerView.bounds.size);
[purikuraContainerView.layer renderInContext:UIGraphicsGetCurrentContext()];
photoFlattened = UIGraphicsGetImageFromCurrentImageContext();
UIGraphicsEndImageContext();


NSEnumerator *enumerator = [[photoContainerView subviews] objectEnumerator];
id object;

while ((object = [enumerator nextObject])) {

[object removeFromSuperview];

}


[photoContainerView release];

photoContainerView = nil;

if(rotPhoto1 != nil){
[rotPhoto1 release];
rotPhoto1 = nil;
}
if(rotPhoto2 != nil){
[rotPhoto2 release];
rotPhoto2 = nil;
}
if(rotPhoto3 != nil){
[rotPhoto3 release];
rotPhoto3 = nil;
}
if(rotPhoto4 != nil){
[rotPhoto4 release];
rotPhoto4 = nil;
}

if(rotPhotoSm1 != nil){
[rotPhotoSm1 release];
rotPhotoSm1 = nil;
}
if(rotPhotoSm2 != nil){
[rotPhotoSm2 release];
rotPhotoSm2 = nil;
}
if(rotPhotoSm3 != nil){
[rotPhotoSm3 release];
rotPhotoSm3 = nil;
}
if(rotPhotoSm4 != nil){
[rotPhotoSm4 release];
rotPhotoSm4 = nil;
}

return photoFlattened;

}



//-----------------------------STOP THE UIACTIVITYINDICATORVIEW---------------------



-(IBAction)stopSpinner:(id)sender
{

[self.view setUserInteractionEnabled:YES];
[myIndicator stopAnimating];
[myIndicator release];
myIndicator = nil;

if(myPattern == 0){
NSLog(@"SINGLE-SHOT MODE");
controller.isSingleShot = TRUE;

}else{

NSLog(@"MULTI-SHOT MODE");
controller.isSingleShot = FALSE;

}

controller.modalTransitionStyle = UIModalTransitionStyleCrossDissolve;
[self presentModalViewController:controller animated:YES];

[controller release];

[allStamps removeAllObjects];
[imageFrames removeAllObjects];


switch (myShots) {
case 1:
[editPhotoData1 release];
break;

case 2:
[editPhotoData1 release];
[editPhotoData2 release];
break;

case 4:
[editPhotoData1 release];
[editPhotoData2 release];
[editPhotoData3 release];
[editPhotoData4 release];
break;

}

/* This is the edited photo that has been onscreen. Processing is now done so it is okay to release it. The UI should be updated and now have a blank, black background instead of the image.
*/
editedPhoto.image = nil;
[editedPhoto release];
editedPhoto = nil;


}

最佳答案

这个问题有一些关于 Cocoa 多线程的好资源:"Where can I find a good tutorial on iPhone/Objective c multithreading?"

我还强烈建议阅读新的 Concurrency Programming Guide ( 但是,请忽略 block 和调度队列,因为 Grand Central Dispatch 在 iPhone OS 上尚不可用 iOS 4.0 只是添加了 block 和 GCD),因为它为使用像 这样的结构提供了强有力的理由NSOperationNSOperationQueue 作为手动创建线程的替代方案。有关手动创建线程的信息,请参阅 Threading Programming Guide .

正如 RC 提到的,多线程 Cocoa 应用程序崩溃的最大根源是同时访问共享资源。 @synchronized 指令不是最快的,如 pointed out by Colin Wheeler ,因此您可能需要使用 NSLock 来保护对共享资源的访问。然而,任何类型的锁定都可能代价高昂,这就是为什么我一直将我的应用程序迁移到使用单宽 NSOperationQueues 来访问这些资源。性能改进非常显着。

Cocoa 和多线程的另一个问题来自用户界面更新。 Cocoa 中的所有 UI 更新都必须在主线程上完成,否则可能会导致不稳定。如果您有后台线程执行计算,请确保将更新 UI 的任何方法包装在 -performSelectorOnMainThread:withObject:waitUntilDone: 方法调用中。

关于iphone - 初学者在 iPhone 上常犯的多线程错误,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/1357108/

26 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com