多线程时检索数据

发布于 2024-12-09 04:19:27 字数 3432 浏览 0 评论 0原文

我在从数据库加载数据时使用多线程。

我正在执行以下操作

dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), 
               ^{
                   // Get data
                   NSDate *pastDate = [CommonHelper getSelectedDateYearBackComponents:[NSDate date]];
                   NSPredicate *predicate = [NSPredicate predicateWithFormat:@"users == %@ && startDate >= %@", objUser,pastDate];
                   NSMutableArray *fetchArray = [DataAccess searchObjectsInUserContext:@"userIngo" :predicate :@"startDate" :NO];

                   if ([fetchArray count] > 0)
                   {
                       dispatch_async(dispatch_get_main_queue(), 
                                     ^{
                                         // Reload table
                                         [self.tableView reloadData]; });
                   }

                   else 
                   {
                       dispatch_async(dispatch_get_main_queue(), 
                        ^{  // calling Webservice
                         });
                   }
                });

,其中 users 是我尝试从中获取数据的实体,objUser 是我要从用户实体检索数据的用户对象

,我的 searchObjectsInUserContext 代码如下

+(NSMutableArray *) searchObjectsInLabContext: (NSString*) entityName : (NSPredicate *) predicate : (NSString*) sortKey : (BOOL) sortAscending
 {
i3EAppDelegate *appDelegate = (i3EAppDelegate *)[[UIApplication sharedApplication] delegate];

NSManagedObjectContext *context = [[NSManagedObjectContext alloc] init];
[context setUndoManager:nil];
[context setPersistentStoreCoordinator:[appDelegate persistentStoreCoordinator]];

// Register context with the notification center
NSNotificationCenter *nc = [NSNotificationCenter defaultCenter];
[nc addObserver:self selector:@selector(mergeChanges:) name:NSManagedObjectContextDidSaveNotification object:context];

NSFetchRequest *request = [[NSFetchRequest alloc] init];
NSEntityDescription *entity = [NSEntityDescription entityForName:entityName inManagedObjectContext:context];
[request setEntity:entity]; 
[request setFetchBatchSize:10];
[request setReturnsObjectsAsFaults:NO];

// If a predicate was passed, pass it to the query
if(predicate != nil)
{
    [request setPredicate:predicate];
}

// If a sort key was passed, use it for sorting.
if(sortKey != nil)
{
    NSSortDescriptor *sortDescriptor = [[NSSortDescriptor alloc] initWithKey:sortKey ascending:sortAscending];
    NSArray *sortDescriptors = [[NSArray alloc] initWithObjects:sortDescriptor, nil];
    [request setSortDescriptors:sortDescriptors];
    [sortDescriptors release];
    [sortDescriptor release];
}

NSError *error;

NSMutableArray *mutableFetchResults = [[context executeFetchRequest:request error:&error] mutableCopy];

if (mutableFetchResults == nil) {

    // Handle the error.
    // NSLog(@"Unresolved error %@, %@", error, [error userInfo]);
    exit(-1);  // Fail

}

[request release];
appDelegate = nil;

return [mutableFetchResults autorelease];
  }

所示我的 searchObjectInUserContext 我使用多个 ManagedObjectContext,这样在多线程处理时它不会给我带来问题,正如 Fred McCann 在他的 博客文章

但是,我的问题出在 searchObjectsInUserContext 中的 NSMutableArray *mutableFetchResults 处,因为即使数据库中有数据,它有时也会返回 0。

有人可以帮助我解决我做错的事情吗?

I am using multithreading while loading data from the database.

I am doing the following

dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), 
               ^{
                   // Get data
                   NSDate *pastDate = [CommonHelper getSelectedDateYearBackComponents:[NSDate date]];
                   NSPredicate *predicate = [NSPredicate predicateWithFormat:@"users == %@ && startDate >= %@", objUser,pastDate];
                   NSMutableArray *fetchArray = [DataAccess searchObjectsInUserContext:@"userIngo" :predicate :@"startDate" :NO];

                   if ([fetchArray count] > 0)
                   {
                       dispatch_async(dispatch_get_main_queue(), 
                                     ^{
                                         // Reload table
                                         [self.tableView reloadData]; });
                   }

                   else 
                   {
                       dispatch_async(dispatch_get_main_queue(), 
                        ^{  // calling Webservice
                         });
                   }
                });

where users is the entity from which I am trying to fetch data and objUser is the user object for whom I am retrieving data from the users entity

and my searchObjectsInUserContext code is like this

+(NSMutableArray *) searchObjectsInLabContext: (NSString*) entityName : (NSPredicate *) predicate : (NSString*) sortKey : (BOOL) sortAscending
 {
i3EAppDelegate *appDelegate = (i3EAppDelegate *)[[UIApplication sharedApplication] delegate];

NSManagedObjectContext *context = [[NSManagedObjectContext alloc] init];
[context setUndoManager:nil];
[context setPersistentStoreCoordinator:[appDelegate persistentStoreCoordinator]];

// Register context with the notification center
NSNotificationCenter *nc = [NSNotificationCenter defaultCenter];
[nc addObserver:self selector:@selector(mergeChanges:) name:NSManagedObjectContextDidSaveNotification object:context];

NSFetchRequest *request = [[NSFetchRequest alloc] init];
NSEntityDescription *entity = [NSEntityDescription entityForName:entityName inManagedObjectContext:context];
[request setEntity:entity]; 
[request setFetchBatchSize:10];
[request setReturnsObjectsAsFaults:NO];

// If a predicate was passed, pass it to the query
if(predicate != nil)
{
    [request setPredicate:predicate];
}

// If a sort key was passed, use it for sorting.
if(sortKey != nil)
{
    NSSortDescriptor *sortDescriptor = [[NSSortDescriptor alloc] initWithKey:sortKey ascending:sortAscending];
    NSArray *sortDescriptors = [[NSArray alloc] initWithObjects:sortDescriptor, nil];
    [request setSortDescriptors:sortDescriptors];
    [sortDescriptors release];
    [sortDescriptor release];
}

NSError *error;

NSMutableArray *mutableFetchResults = [[context executeFetchRequest:request error:&error] mutableCopy];

if (mutableFetchResults == nil) {

    // Handle the error.
    // NSLog(@"Unresolved error %@, %@", error, [error userInfo]);
    exit(-1);  // Fail

}

[request release];
appDelegate = nil;

return [mutableFetchResults autorelease];
  }

So in my searchObjectInUserContext I use multiple managedObjectContext so that it does not create problems for me while multithreading as explained by Fred McCann in his blog post.

However, my problem is at NSMutableArray *mutableFetchResults in my searchObjectsInUserContext because it returns 0 at times even though there is data in the database.

Can someone help me with what I am doing wrong?

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(1

固执像三岁 2024-12-16 04:19:27
  1. 你正在泄露你创建的上下文;你永远不会释放它。
  2. 无需注册为观察者,因为您永远不会在该上下文中进行保存。
  3. 为什么要制作上下文的可变副本?这很少有任何有用的目的。
  4. 怎么知道数据库里有数据呢?
  5. 该方法是否在后台线程上运行?

更新

您的获取没有任何问题,所以我怀疑问题可能是时间问题之一。此提取是否在另一个线程保存之前运行?这可以解释您所看到的行为。

另外,为什么要在后台线程上运行它?您是否遇到需要像这样的后台搜索的性能问题?

更新2

首先,我仍然质疑后台获取的必要性。这通常是在遇到性能问题时保留的,因为获取速度非常快。

其次,您在后台队列上获取数据,但随后不对获取的数据执行任何操作。你不会把它交给桌子(无论如何这都会很糟糕),你只是把它拿起来然后扔掉。

如果您只是为了计数而获取,则不要获取,请执行 -[NSManagedObjectContext -countForFetchRequest: error:]。它会更快,并且不需要后台队列调用。

如果你期望对结果做一些事情,那么你就会遇到问题。 NSManagedObject 的实例不能跨越线程/队列边界。因此,获取后台队列对 UI 的影响很小。您需要在主队列/主线程上获取这些对象。如果你不这样做,你将会崩溃,因为核心数据不允许它。

最后,你的后台队列对你来说弊大于利,并且它们没有解决你想要解决的问题。

  1. You are leaking the context you create; you never release it.
  2. There is no need to register as an observer because you are never saving with that context.
  3. Why are you making a mutable copy of the context? That rarely serves any useful purpose.
  4. How do you know there is data in the database?
  5. Is this method being run on a background thread?

Update

There is nothing wrong with your fetch so I suspect the issue might be one of timing. Is this fetch being run before another thread saves? That would explain the behavior you are seeing.

Also, why are you running this on a background thread? Are you seeing a performance issue that requires a background search like this?

Update 2

First, I still question the need for the background fetching. That is normally reserved for when you have performance issues as fetching is very fast.

Second, you fetch on a background queue but then you don't do anything with the data you fetched. You do not hand it off to the table (which would be bad anyway) you just fetch and throw it away.

If you are fetching just to count then don't fetch, do a -[NSManagedObjectContext -countForFetchRequest: error:]. It will be even faster and removes the need for the background queue call.

If you are expecting to do something with the results you have an issue. Instances of NSManagedObject cannot cross a thread/queue boundary. So fetching on the background queue does very little for the UI. You need to fetch those objects on the main queue/main thread. If you don't you will crash because Core Data does not allow it.

In the end, your background queues are doing you more harm than good and they are not solving the problem you are trying to solve.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文