i am working on threading....i came across this:
-(void)didRecieveResponse:(NSArray*)responseDic{
//Update DB status to '2', which means everything needs to b deleted
[[MediaService sharedInstance] updateMedia:2];
self.projectArray = responseDic;
dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{
for (int j = 0; j<[self.projectArray count]; j++) {
ProjectJsonModel *pModel = [self.projectArray objectAtIndex:j];
[self parseArray:pModel.imageArray project:pModel ptype:1];
[self parseArray:pModel.pdfArray project:pModel ptype:2];
[self parseArray:pModel.videoArray project:pModel ptype:3];
Media *tmpMedia = [[Media alloc] init];
tmpMedia.projectId = pModel.projetId;
tmpMedia.projectName = pModel.projectName;
// NSLog(#"DB project naem = %#",pModel.projectName);
tmpMedia.fileType = 4;
tmpMedia.fileLink = NULL;
tmpMedia.fileName = NULL;
//NSURL *fileUrl = [NSURL URLWithString:tmpMedia.fileLink];
//tmpMedia.fileName = [fileUrl lastPathComponent];
tmpMedia.status = 4;
[[MediaService sharedInstance] insertMedia:tmpMedia];
[tmpMedia release];
}
[self checkDbForDownload];
dispatch_async(dispatch_get_main_queue(), ^(void) {
//Stop your activity indicator or anything else with the GUI
//Code here is run on the main thread
});
});
which stores all online data into database.and it will displays in app. When it is checking for update application stops working.
In that break point is not entering in this loop, why?
The code in dispatch_async would run asynchronously. Debugging this from outer block of code would step out of the entire dispatch_async as a single line and will not step into the code block within. Put an additional break point in for (int j = 0; j<[self.projectArray count]; j++) { instead of stepping in from outer block to debug the code. This would stop the asyc background thread to stop when executing.
Related
for (int s=0; s<masterArray.count; s++) {
for (int i=0; i<countOfSub1; i++) {
}
}
vast amount of data in this loop so, i want get when s=0 then get all data of second loop then after s=1 then after get all data of second loop so on, then how can i set thread in this code. Thanks.
You can use it by the following example
for (int s=0; s<masterArray.count; s++) {// your main loop starts here
dispatch_semaphore_t sem;
sem = dispatch_semaphore_create(0);
dispatch_queue_t concurrentQueue = dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0);
dispatch_async(concurrentQueue, ^{
for (int i=0; i<countOfSub1; i++) {// Inner loop in a thread
//your work here
}
dispatch_semaphore_signal(sem);
});
dispatch_semaphore_wait(sem, DISPATCH_TIME_FOREVER); // main loop waiting to be triggered from sub loop. (inner loop)
}
The CRASH is:
This application is modifying the autolayout engine from a background thread, which can lead to engine corruption and weird crashes. This will cause an exception in a future release.
It is clear that the problem is that every time the ui is changed must be done on the main thread. In theory this might work
dispatch_async(dispatch_get_main_queue(), {
// code here
})
My Function is:
- (void)requestInBlock:(NSString *)keyThumbnails withArrayQuantity:(NSMutableArray *)quantityArray andOriginalQuantity:(NSInteger)originalQuantity
{
int limit = 5;
NSMutableArray *arrayFive = [[NSMutableArray alloc] init];
NSInteger idQuantityOriginalCount = [quantityArray count];
for (NSInteger i = 0; i < MIN(limit, idQuantityOriginalCount); i ++) {
[arrayFive addObject:[quantityArray objectAtIndex:0]];
[quantityArray removeObjectAtIndex:0];
}
NSInteger idLimitArrayCount = [arrayFive count];
NSInteger __block countProductsRequestLimit = 0;
for (NSNumber *j in arrayFive) {
UIImageView * thumbnailImageView = [[UIImageView alloc] initWithFrame:CGRectMake(xposThumbnails, 0, ratio * 2, 47)];
[thumbnailsView addSubview:thumbnailImageView];
NSURL *imageUrl = [NSURL URLWithString:[NSString stringWithFormat:#"https://s3-us-west-2.amazonaws.com/xxxxxxxxxxxxxx/%#_%#.jpg",keyThumbnails,j]];
[Utils loadFromURL:imageUrl callback:^(UIImage *image) {
countProductsRequestLimit++;
countThumbnailsGlobal++;
[thumbnailImageView setImage:image];
[cutVideoScroll addSubview:thumbnailsView];
if (!image) {
NSMutableDictionary *collectInfoFailImage = [[NSMutableDictionary alloc] init];
[collectInfoFailImage setValue:thumbnailImageView forKey:#"image"];
[collectInfoFailImage setValue:imageUrl forKey:#"imageUrl"];
[thumbnailsWithError addObject:collectInfoFailImage];
collectInfoFailImage = nil;
}
if (countThumbnailsGlobal == originalQuantity) {
[arrayFive removeAllObjects];
[self performSelector:#selector(reloadThumbnailsWithError) withObject:nil afterDelay:3];
} else if (idLimitArrayCount == countProductsRequestLimit) {
[arrayFive removeAllObjects];
[self requestInBlock:keyThumbnails withArrayQuantity:quantityArray andOriginalQuantity:originalQuantity];
}
}];
xposThumbnails += (ratio * 2);
}
loadingTimeLine.layer.zPosition = -1;
lblloadingTimeLine.layer.zPosition = -1;
}
I think the mistake is happening here loadFromURL. (It is not sure about this, because in all devices with I do my tests, this never happens, someone outside informed me and sent me error logs)
My question is:
which part of this code may be modifying the autoLayout, maybe [cutVideoScroll addSubview:thumbnailsView];?
Why only occurs on an iPod?
UPDATE:
I'm testing with.
dispatch_async(dispatch_get_main_queue(), ^{
[thumbnailImageView setImage:image];
[cutVideoScroll addSubview:thumbnailsView];
});
But error persist.
Thanks for your time.
You got it right, adding subview to view trigger layoutSubviews. So you should addViews only in main thread.
Maybe you have some code specifically for iPhone / iPod in any method which you override?
It seems to be a combination of 2 things.
dispatch_async(dispatch_get_main_queue(), ^{
[thumbnailImageView setImage:image];
[cutVideoScroll addSubview:thumbnailsView];
});
and in all cases, he was added to thumbnailImageView the image regardless validation if (! image)
I have two methods which run on a serial queue. Each method return a copy of some class. I'm trying to achieve thread safety solution while also mainting data integrity.
for example:
-(Users *) getAllUsers
{
__block copiedUsers;
dispatch_sync(_backgroundQueue, ^{
copiedUsers = [self.users copy]; // return copy object to calling thread.
});
return copiedUsers;
}
-(Orders *) getAllOrders
{
__block copiedOrders;
dispatch_sync(_backgroundQueue, ^{
copiedOrders = [self.Orders copy]; // return copy object to calling thread.
});
return copiedOrders;
}
In addition to this two methods, I have a worker class that add/remove users and orders, all done via a serial queue backgroundQueue.
If in the main thread I call getAllUsers and then getAllOrders right after the other my data integrity isn't safe because between the two calls the worker class might have changed the model.
my question is how can I make to the caller a nice interface that allows multiple methods to run atomically?
Model is only updated from backgroundQueue serial queue.
Client talks to model via a method that receives a block that runs in the background queue.
In addition, not to freeze main thread, I create another queue and run a block that talks with the gateway method.
P.S - attention that dispatch_sync is called only in runBlockAndGetNeededDataSafely to avoid deadlocks.
Code sample:
aViewController.m
ManagerClass *m = [ManagerClass new];
dispatch_queue_t q = dispatch_queue_create("funnelQueue", DISPATCH_QUEUE_SERIAL);
dispatch_block_t block_q = ^{
__Users *users;
__Orders *orders;
[manager runBlockAndGetNeededDataSafely:^
{
users = [manager getUsers];
orders = [manager getOrders];
dispatch_async(dispatch_get_main_queue(),
^{
// got data safely - no thread issues, copied objects. update UI!
[self refreshViewWithUsers:users
orders:orders];
});
}];
}
dispatch_async(q, block_q);
Manager.m implementation:
-(void) runBlockInBackground:(dispatch_block_t) block
{
dispatch_sync(self.backgroundQueue, block);
}
-(Users *) getAllUsers
{
return [self.users copy];
}
-(Orders *) getAllOrders
{
return [self.Orders copy];
}
To answer your question about how to checking the current queue:
First when you create the queue, give it a tag:
static void* queueTag = &queueTag;
dispatch_queue_t queue = dispatch_queue_create("a queue", 0);
dispatch_queue_set_specific(queue, queueTag, queueTag, NULL);
and then run a block like this:
-(void)runBlock:(void(^)()) block
{
if (dispatch_get_specific(queueTag) != NULL) {
block();
}else {
dispatch_async(self.queue, block);
}
}
Your example doesn't work. I suggest to use completion callback. You should have an option to know when the worker finish his job to return to value.
- (void)waitForCompletion:(BOOL*)conditions length:(int)len timeOut:(NSInteger)timeoutSecs {
NSDate *timeoutDate = [NSDate dateWithTimeIntervalSinceNow:timeoutSecs];
BOOL done = YES;
for (int i = 0; i < len; i++) {
done = done & *(conditions+i);
}
do {
[[NSRunLoop currentRunLoop] runMode:NSDefaultRunLoopMode beforeDate:timeoutDate];
if([timeoutDate timeIntervalSinceNow] < 0.0)
break;
//update done
done = YES;
for (int i = 0; i < len; i++) {
done = done & *(conditions+i);
}
} while (!done);
}
-(void) getAllUsers:(void(^)(User* user, NSError* error))completion
{
dispatch_async(_backgroundQueue, ^{
BOOL condition[2] = [self.userCondition, self.orderCondition];
[self waitForCompletion: &condition[0] length:2 timeOut:60];
if (completion) {
completion([self.users copy], nil);
}
});
}
I have 3 blocks of code that must execute one by one after previous finished. My implementation not works. I need some help to do it. My code bellow.
for (NSString *i in items)
{
[[RequestAPI sharedInstance]downloadImage:i completion:^(AFHTTPRequestOperation *operation, UIImage *image, NSError *error) {
//here main thread I receive images and go to BG
dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_BACKGROUND, 0), ^{
// here I save image on disk and get path
NSString *path = [ImageManager saveImageToDisk:image toEntity:entity withparams:#{#"save" : #"lala"}];
__block NSMutableDictionary *attachments = [NSMutableDictionary dictionary];
__block NSMutableArray *photoPaths = [NSMutableArray array];
dispatch_async(dispatch_get_main_queue(), ^{
//block1. here I load entity and dictionary from it with NSKeyedUnarchiver from CD and set to it image path
if (entity.attachments)
{
attachments = [NSKeyedUnarchiver unarchiveObjectWithData:entity.attachments];
if (attachments[type])
{
photoPaths = attachments[type];
}
}
dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_BACKGROUND, 0), ^{
//block2. here I check all images equality ti themselves in entity
BOOL haveDublicate = NO;
NSData *i = [ImageManager imageDataFromPath:path];
NSArray *photoImages = [ImageManager imageDatasFromPaths:photoPaths];
for (NSData *saved in photoImages)
{
if ([saved isEqualToData: i])
{
haveDublicate = YES;
}
}
if (!photoPaths)
{
photoPaths = [NSMutableArray array];
}
dispatch_async(dispatch_get_main_queue(), ^{
//block3. and finally if all ok I save image path, change load counter and post notification
if (path.length
&& ![photoPaths containsObject:path]
&& !haveDublicate
)
{
[photoPaths addObject:path];
[savedLinks setObject:photoPaths forKey:type];
entity.attachments = [NSKeyedArchiver archivedDataWithRootObject:savedLinks];
[self saveContext];
}
[RequestAPI sharedInstance].downloadsCount -= 1;
[[NSNotificationCenter defaultCenter]postNotificationName:kReloadFeedData object:nil];
});
});
});
});
}];
As dispatch_async says they will be executed asynchronous and not synchronous as you expected. Use dispatch_sync instead.
If you want to execute your code on a separate thread simple do the following
// create your thread
dispatch_queue_t queue = dispatch_queue_create("My Other Queue", 0);
// execute your synchronous block on the thread you've just created
dispatch_sync(queue,^{
// add your implementation here to be executed on your separate thread
dispatch_sync(dispatch_get_main_queue()^{
// update your UI here. Don't forget you can only update UI on the main thread
});
});
The code below is called each time a scrollview scroll and if user scroll it multiple times, it crashed the code. How do i make sure only 1 code execute at a time or threadsafe?
[self.cv addInfiniteScrollingWithActionHandler:^{
[weakSelf loadNextPage];
}];
Here is example
- (void)_startExperiment {
FooClass *foo = [[FooClass alloc] init];
dispatch_queue_t queue = dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0);
for (int i = 0; i < 4; ++i) {
dispatch_async(queue, ^{
[foo doIt];
});
}
[foo release];
}
Detail is Here
The common pattern is to use a mutex to protect a critical section of code where the structure is accessed and/or modified.
just go through this link->
Does #synchronized guarantees for thread safety or not?